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.

32
demandé sur Jess 2008-12-01 10:48:38

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:

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

39
répondu Winston Smith 2008-12-01 09:23:09

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.

12
répondu teknopaul 2014-05-21 13:26:27

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;
8
répondu CupOfTea 2017-05-23 12:32:23

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.

2
répondu Felipe 2014-04-22 15:55:58