DB2 ha una dichiarazione “inserisci o aggiorna”?

Dal mio codice (Java) voglio assicurarmi che una riga esista nel database (DB2) dopo che il mio codice è stato eseguito.

Ora il mio codice esegue una select e se non viene restituito alcun risultato, fa un insert . Non mi piace davvero questo codice poiché mi espone a problemi di concorrenza durante l’esecuzione in un ambiente multi-thread.

Quello che mi piacerebbe fare è mettere questa logica in DB2 invece che nel mio codice Java. DB2 ha una istruzione insert-or-update ? O qualcosa di simile che posso usare?

Per esempio:

 insertupdate into mytable values ('myid') 

Un altro modo per farlo sarebbe probabilmente quello di fare sempre l’inserto e catturare “la chiave primaria del codice SQL -803 esiste già”, ma vorrei evitarlo se ansible.

Sì, DB2 ha l’istruzione MERGE, che eseguirà un UPSERT (aggiornamento o inserimento).

 MERGE INTO target_table USING source_table ON match-condition {WHEN [NOT] MATCHED THEN [UPDATE SET ...|DELETE|INSERT VALUES ....|SIGNAL ...]} [ELSE IGNORE] 

Vedere:

http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?topic=/com.ibm.db2.udb.admin.doc/doc/r0010873.htm

Ho trovato questo thread perché avevo davvero bisogno di un one-liner per DB2 INSERT o UPDATE.

La seguente syntax sembra funzionare, senza richiedere una tabella temporanea separata.

Funziona usando VALUES () per creare una struttura di tabella. Il SELECT * sembra in eccesso IMHO ma senza di esso ottengo errori di syntax.

 MERGE INTO mytable AS mt USING ( SELECT * FROM TABLE ( VALUES (123, 'text') ) ) AS vt(id, val) ON (mt.id = vt.id) WHEN MATCHED THEN UPDATE SET val = vt.val WHEN NOT MATCHED THEN INSERT (id, val) VALUES (vt.id, vt.val) ; 

se devi inserire più di una riga, la parte VALUES può essere ripetuta senza dover duplicare il resto.

 VALUES (123, 'text'), (456, 'more') 

Il risultato è una singola istruzione che può INSERIRE O AGGIORNARE una o più righe presumibilmente come un’operazione atomica.

Si spera che questa risposta risponda pienamente alla query che MrSimpleMind aveva in uso-update-and-insert-in-same-query e fornire un semplice esempio di lavoro dell’istruzione MERGE DB2 con uno scenario di inserimento e aggiornamento in un colpo solo (registrazione con L’ID 2 viene aggiornato e viene inserito l’ID 3 del record).

 CREATE TABLE STAGE.TEST_TAB ( ID INTEGER, DATE DATE, STATUS VARCHAR(10) ); COMMIT; INSERT INTO TEST_TAB VALUES (1, '2013-04-14', NULL), (2, '2013-04-15', NULL); COMMIT; MERGE INTO TEST_TAB T USING ( SELECT 3 NEW_ID, CURRENT_DATE NEW_DATE, 'NEW' NEW_STATUS FROM SYSIBM.DUAL UNION ALL SELECT 2 NEW_ID, NULL NEW_DATE, 'OLD' NEW_STATUS FROM SYSIBM.DUAL ) AS S ON S.NEW_ID = T.ID WHEN MATCHED THEN UPDATE SET (T.STATUS) = (S.NEW_STATUS) WHEN NOT MATCHED THEN INSERT (T.ID, T.DATE, T.STATUS) VALUES (S.NEW_ID, S.NEW_DATE, S.NEW_STATUS); COMMIT; 

Un altro modo è quello di eseguire queste 2 query. È più semplice di creare un’istruzione MERGE:

 update TABLE_NAME set FIELD_NAME=xxxxx where MyID=XXX; INSERT INTO TABLE_NAME values (MyField1,MyField2) WHERE NOT EXISTS(select 1 from TABLE_NAME where MyId=xxxx); 

La prima query aggiorna semplicemente il campo di cui hai bisogno, se il MyId esiste. Il secondo inserisce la riga in db se MyId non esiste.

Il risultato è che solo una delle query viene eseguita nel tuo db.