Does DB2 have an “insert or update” statement?

2019-01-06 14:09发布

From my code (Java) I want to ensure that a row exists in the database (DB2) after my code is executed.

My code now does a select and if no result is returned it does an insert. I really don't like this code since it exposes me to concurrency issues when running in a multi-threaded environment.

What I would like to do is to put this logic in DB2 instead of in my Java code. Does DB2 have an insert-or-update statement? Or anything like it that I can use?

For example:

insertupdate into mytable values ('myid')

Another way of doing it would probably be to always do the insert and catch "SQL-code -803 primary key already exists", but I would like to avoid that if possible.

4条回答
爷的心禁止访问
2楼-- · 2019-01-06 14:23

Yes, DB2 has the MERGE statement, which will do an UPSERT (update or insert).

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

See:

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

查看更多
3楼-- · 2019-01-06 14:30

This response is to hopefully fully answer the query MrSimpleMind had in use-update-and-insert-in-same-query and to provide a working simple example of the DB2 MERGE statement with a scenario of inserting AND updating in one go (record with ID 2 is updated and record ID 3 inserted).

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;
查看更多
爷、活的狠高调
4楼-- · 2019-01-06 14:35

Another way is to execute this 2 queries. It's simpler than create a MERGE statement:

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

The first query just updateS the field you need, if the MyId exists. The second insertS the row into db if MyId does not exist.

The result is that only one of the queries is executed in your db.

查看更多
可以哭但决不认输i
5楼-- · 2019-01-06 14:37

I found this thread because I really needed a one-liner for DB2 INSERT OR UPDATE.

The following syntax seems to work, without requiring a separate temp table.

It works by using VALUES() to create a table structure . The SELECT * seems surplus IMHO but without it I get syntax errors.

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

if you have to insert more than one row, the VALUES part can be repeated without having to duplicate the rest.

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

The result is a single statement that can INSERT OR UPDATE one or many rows presumably as an atomic operation.

查看更多
登录 后发表回答