DB2是否有“插入或更新”语句?

时间:2008-12-01 07:48:38

标签: sql database db2 insert-update upsert

从我的代码(Java)中我想确保在执行代码后数据库(DB2)中存在一行。

我的代码现在执行select,如果没有返回结果,则会执行insert。我真的不喜欢这个代码,因为它在多线程环境中运行时会让我遇到并发问题。

我想要做的是将这个逻辑放在DB2而不是我的Java代码中。 DB2是否有insert-or-update语句?或者我可以使用的任何类似的东西?

例如:

insertupdate into mytable values ('myid')

另一种方法可能是始终执行insert并捕获“SQL-code -803主键已经存在”,但我想尽可能避免这种情况。

5 个答案:

答案 0 :(得分:40)

是的,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

答案 1 :(得分:15)

我找到了这个帖子,因为我真的需要DB2 INSERT或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')

结果是一个语句,可以插入或更新一行或多行,可能是一个原子操作。

答案 2 :(得分:9)

这个响应有希望完全回答MrSimpleMind在use-update-and-insert-in-same-query中的查询,并提供一个有效的DB2 MERGE语句示例,其中包含一次插入和更新的方案(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;

答案 3 :(得分:2)

另一种方法是执行这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存在,第一个查询只会更新您需要的字段。 如果MyId不存在,则第二次将行插入db。

结果是在您的数据库中只执行了一个查询。

答案 4 :(得分:0)

我从休眠项目开始,休眠项目允许您保存或更新()。 我将该项目转换为JDBC项目,问题是保存和更新。 我想同时使用JDBC保存和更新。 因此,我进行了一些研究,并偶然发现了DUPLICATE KEY UPDATE:

String sql="Insert into tblstudent (firstName,lastName,gender) values (?,?,?) 
ON DUPLICATE KEY UPDATE 
firstName= VALUES(firstName),
lastName= VALUES(lastName),
gender= VALUES(gender)";

上述代码的问题在于它两次更新了主键, 每个mysql文档: 受影响的行只是一个返回码。 1行表示已插入,2表示已更新,0表示未发生任何事情。

我引入了id并将其递增到1。现在我正在递增id的值而不是mysql。

String sql="Insert into tblstudent (id,firstName,lastName,gender) values (?,?,?) 
ON DUPLICATE KEY UPDATE 
id=id+1,
firstName= VALUES(firstName),
lastName= VALUES(lastName),
gender= VALUES(gender)";

上面的代码对我来说都适用于插入和更新。

希望它也对您有用。