web-dev-qa-db-ja.com

DB2には「挿入または更新」ステートメントがありますか?

コード(Java)から、コードの実行後にデータベース(DB2)に行が存在することを確認したい。

私のコードはselectを実行し、結果が返されない場合はinsertを実行します。このコードは、マルチスレッド環境で実行しているときに並行性の問題にさらされるため、本当に好きではありません。

私がやりたいのは、このロジックをJavaコードではなく、DB2に配置することです。DB2にはinsert-or-updateステートメントがありますか?

例えば:

insertupdate into mytable values ('myid')

それを行う別の方法は、おそらく常に「SQL-code -803主キーが既に存在する」という挿入とキャッチを行うことですが、可能であればそれを避けたいと思います。

35
Mikael Eriksson

はい、DB2にはMERGEステートメントがあり、UPSERT(更新または挿入)を実行します。

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

見る:

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

https://www.ibm.com/support/knowledgecenter/en/SS6NHC/com.ibm.swg.im.dashdb.sql.ref.doc/doc/r0010873.html

https://www.ibm.com/developerworks/community/blogs/SQLTips4DB2LUW/entry/merge?lang=en

40
Winston Smith

このスレッドは、DB2 INSERT OR UPDATE。

次の構文は、別の一時テーブルを必要とせずに機能するようです。

VALUES()を使用してテーブル構造を作成します。 SELECT *は私見の余剰のようですが、それなしでは構文エラーになります。

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)
;

複数の行を挿入する必要がある場合、残りを複製せずにVALUES部分を繰り返すことができます。

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

結果は、おそらくアトミック操作として1つまたは複数の行をINSERT OR UPDATEすることができる単一のステートメントです。

15
teknopaul

この応答は、MrSimpleMindが se-update-and-insert-in-same-query で行ったクエリに完全に答え、さらにAND一括更新(ID 2のレコードが更新され、レコードID 3が挿入されます)。

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;
10
CupOfTea

別の方法は、この2つのクエリを実行することです。 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);

MyIdが存在する場合、最初のクエリは必要なフィールドを更新します。 2番目は、MyIdが存在しない場合、dbに行を挿入します。

その結果、データベースではクエリの1つだけが実行されます。

2
Felipe