2008-12-01 289 views
30

从我的代码(Java)我想确保在我的代码执行后数据库(DB2)中存在一行。DB2是否有“插入或更新”语句?

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

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

例如:

insertupdate into mytable values ('myid') 

做的另一种方式,它可能将是永远做插入和捕获“SQL代码-803主键已经存在”,但我想避免,如果可能的。

+0

每个线程有一个事务不是更好吗?数据库管理系统在多线程下运行良好,这就是交易发明的原因。他们会解决并发问题。 – bortzmeyer 2008-12-01 10:58:16

+0

这不会解决并发问题,因为事务只能通过在已经存在的行上进行阻塞来工作。如果行不存在,事务就不能阻塞它,所以这种操作仍然对并发问题开放 – Richard 2011-11-30 15:57:55

回答

38

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

+2

示例很有用:__merge into mytable using(values('col1','col2'))as tmp(代码,名称)mytable.code = tmp.code 匹配时更新设置名称= col2'__ – agad 2017-01-03 13:05:30

7

这种反应是希望充分回答查询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; 
+1

为我工作。谢谢 – Li3ro 2013-11-20 09:34:27

+0

我想指出一些ibm数据库使用`SYSIBM.SYSDUMMY1`作为虚拟表而不是`SYSIBM.DUAL` – tgdn 2017-07-19 08:05:00

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不存在,第二次插入到db的行。

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

11

我发现这个线程是因为我真的需要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') 

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