2010-01-13 78 views
5

我試圖插入可能已經存在或可能不存在的單個行。我想避免先選擇它,並且/或者如果確實存在-803的話。我已經做了一些研究,並嘗試忽略和合並語句,但不斷收到語法錯誤。在任何情況下,我都不想從另一個表中複製數據 - 因此,合併並不合適。
DB2 SQL中是否有某種方式來發佈防故障插入,而不必爲此編寫代碼?換句話說,是否有一些插入語法可以保證數據在不存在的情況下將被添加,或者即使它不會返回零狀態?試圖避免-803在DB2中插入

回答

2

總之,答案是否定的。總之,這一切都取決於您在桌面上設置的限制條件。如果您試圖針對某列具有唯一約束的表執行插入操作,並且您試圖插入的數據已存在,那麼您將在DB2(以及任何其他RDBMS)中發生錯誤。

在這種情況下,您最好的選擇可能是編寫一個存儲過程,在創建它之前檢查記錄是否已經存在。

+2

更好的是:不要浪費時間進行存在檢查,讓存儲過程執行插入操作,並只處理-803(SQL0803N)錯誤。 更好:只需讓應用程序檢查插入的返回碼並處理-803錯誤。 – 2010-01-14 17:27:48

+0

感謝您的快速響應。我希望DB2具有與「忽略」參數等價的功能,但沒有這種運氣。 Mike – 2010-01-15 13:44:33

+0

嘗試處理-803並進行更新,但是即使整個過程成功,這也會在日誌中留下堆棧跟蹤,從而導致其他人提出問題。所以,我正在更改代碼來首先進行存在檢查。感謝所有的建議。 – 2010-03-18 14:13:11

7

MERGE 合適,因爲您可以動態地在USING子句中提供值(請參閱http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?topic=/com.ibm.db2.udb.admin.doc/doc/r0010873.htm中的示例5)。

但MERGE是一個DB2 V8.2特性!你可能在V8.1上,不是嗎?

如果要實現生存確認是這樣的:

SELECT 
if (found) UPDATE else INSERT 

提防的併發問題:兩個併發線程可能都找不到列,然後都嘗試插入,即使有圍繞上面的代碼交易。爲確保不會發生這種情況,您需要使用WITH RR USE AND KEEP UPDATE LOCKS在上述SELECT語句中獲取帶有可重複讀取的更新鎖定。

+0

如果你執行'INSERT',捕獲'-803',然後執行'UPDATE',那麼併發性問題仍然是一個問題? – 2014-11-25 20:58:01

2

您可以執行update語句,如果返回0結果更新,則執行insert語句。

2

您可以使用sysibm.sysdummy表(或Oracle或更高版本的DB2中更好的雙重命名)執行此操作。如果你想要插入一個不存在的行,但是如果它存在的話返回0,這將很好地工作。 AFAIK,你不能使用這種方法更新一行,你將需要使用合併。

要執行此操作,您需要在表格上使用主鍵或唯一鍵。您插入到表中,在表中不存在與您的主索引或唯一索引匹配的表的過程中,從雙重選擇中選擇所有值。

insert into table (column1, column2, column3, column4, column5) 
select 'A', 'B', 'C', 'D', 'E' from dual where not exists (select * from table where column1 = 'A'); 

我發現這是非常有用的,我有多個進程插入到表的情況下,我不能保證這些插入的順序。您可以通過返回值檢測插入是否成功,如果成功則返回值爲1,如果不成功則返回0