41

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

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

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

例如:

insertupdate into mytable values ('myid')

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

4

5 回答 5

43

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

于 2008-12-01T09:23:09.637 回答
19

我找到了这个线程,因为我真的需要一个用于 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')

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

于 2014-05-21T13:26:27.820 回答
11

此响应希望能完全回答 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;
于 2013-04-16T08:44:46.730 回答
3

另一种方法是执行这 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 中。

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

于 2014-04-22T15:34:20.847 回答
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)";

上面的代码适用于我的插入和更新。

希望它也适用于你。

于 2020-12-18T04:51:58.353 回答