Est-ce que DB2 a une déclaration" insérer ou mettre à jour"?
de mon code (Java) je veux m'assurer qu'une ligne existe dans la base de données (DB2) après l'exécution de mon code.
Mon code fait maintenant une select
et si aucun résultat n'est retourné, il fait un insert
. Je n'aime vraiment pas ce code car il m'expose à des problèmes de concurrence quand je tourne dans un environnement multi-threadé.
ce que je voudrais faire est de mettre cette logique dans DB2 plutôt que dans mon code Java.
Est-ce que DB2 a un insert-or-update
déclaration? Ou quelque chose comme ça que je peux utiliser?
par exemple:
insertupdate into mytable values ('myid')
une autre façon de le faire serait probablement de toujours faire l'insertion et la capture" SQL-code -803 la clé primaire existe déjà", mais je voudrais éviter cela si possible.
4 réponses
Oui, DB2 a l'instruction MERGE, qui va faire un UPSERT (update ou insert).
MERGE INTO target_table USING source_table ON match-condition
{WHEN [NOT] MATCHED
THEN [UPDATE SET ...|DELETE|INSERT VALUES ....|SIGNAL ...]}
[ELSE IGNORE]
voir:
j'ai trouvé ce thread parce que j'avais vraiment besoin d'une doublure unique pour insérer ou mettre à jour DB2.
la syntaxe suivante semble fonctionner, sans exiger une table de température séparée.
il fonctionne en utilisant des valeurs() pour créer une structure de table . Le SELECT * semble excédentaire IMHO mais sans lui j'obtiens des erreurs de syntaxe.
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)
;
si vous devez insérer plus d'une ligne, la partie valeurs peut être répétée sans avoir à dupliquer reste.
VALUES
(123, 'text'),
(456, 'more')
le résultat est une simple instruction qui peut insérer ou mettre à jour une ou plusieurs lignes probablement comme une opération atomique.
cette réponse est d'utiliser-update-and-insert-in-same-query et de fournir un exemple simple de travail de la déclaration de fusion DB2 avec un scénario d'insertion et de mise à jour en une seule fois (l'enregistrement avec ID 2 est mis à jour et l'enregistrement ID 3 inséré).
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;
une autre façon est d'exécuter ces 2 requêtes. C'est plus simple que de créer une déclaration de fusion:
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 première requête ne fait que mettre à jour le champ dont vous avez besoin, si le MyId existe. La seconde insère la ligne dans db si MyId n'existe pas.
le résultat est qu'une seule des requêtes est exécutée dans votre base de données.