从我的代码(Java)我想确保在执行代码后数据库(DB2)中存在一行.
我的代码现在执行了一个select
,如果没有返回结果,它会执行insert
.我真的不喜欢这个代码,因为它在多线程环境中运行时会让我遇到并发问题.
我想要做的是将这个逻辑放在DB2而不是我的Java代码中.DB2有insert-or-update
声明吗?或者我可以使用的任何类似的东西?
例如:
insertupdate into mytable values ('myid')
另一种方法可能是始终执行insert并捕获"SQL-code -803主键已存在",但我想尽可能避免这种情况.
是的,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
我找到了这个线程,因为我真的需要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')
结果是一个语句可以插入或更新一行或多行,可能是一个原子操作.
这个响应有希望完全回答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;