2008-12-01 85 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') 

結果是一個單獨的語句,可以插入或更新一個或多個行,可能是一個原子操作。