我已經在C#中創建了兩個線程,我並行地調用了兩個單獨的函數。這兩個函數都從XYZ表中讀取最後一個ID,並插入值爲ID + 1的新記錄。這裏ID列是主鍵。當我執行這兩個函數時,我得到主鍵違規錯誤。這兩個函數具有以下查詢:在SQL Server 2008中的主鍵違規錯誤
insert into XYZ values((SELECT max(ID)+1 from XYZ),'Name')
似乎這兩個函數都在讀取值,並嘗試插入具有相同的值。 我該如何解決這個問題..?
我已經在C#中創建了兩個線程,我並行地調用了兩個單獨的函數。這兩個函數都從XYZ表中讀取最後一個ID,並插入值爲ID + 1的新記錄。這裏ID列是主鍵。當我執行這兩個函數時,我得到主鍵違規錯誤。這兩個函數具有以下查詢:在SQL Server 2008中的主鍵違規錯誤
insert into XYZ values((SELECT max(ID)+1 from XYZ),'Name')
似乎這兩個函數都在讀取值,並嘗試插入具有相同的值。 我該如何解決這個問題..?
讓數據庫處理爲您選擇ID。從上面的代碼可以看出,你真正想要的是一個自動遞增的整數ID列,數據庫肯定能夠爲你處理。所以設置你的表正確,而是你目前的INSERT語句,這樣做:
insert into XYZ values('Name')
如果數據庫表已經建立了,我相信你可以發出類似聲明:
alter table your_table modify column you_table_id int(size) auto_increment
最後,如果這些解決方案都不能滿足任何原因(包括,正如您在評論部分中所指出的,無法編輯表模式),那麼您可以作爲註釋中建議的其他用戶之一併創建一個同步方法來查找下一個ID。基本上只需創建一個返回int的靜態方法,在該靜態方法中發出您的select id語句,並使用返回的結果將下一條記錄插入到表中。由於此方法不能保證插入成功(由於外部應用程序也能夠插入到同一個表中),所以您還必須捕獲異常並在失敗時重試)。
將ID列設置爲「標識」列。然後,你可以執行你的查詢爲:
insert into XYZ values('Name')
我認爲你不能使用ALTER TABLE來更改列是身份創建列之後。使用Managament Studio將此列設置爲Identity。如果你的表有很多行,這可能是一個長時間運行的過程,因爲它實際上將你的數據複製到一個新表(將執行表重新創建)。
最有可能在您的Managament Studio中禁用此選項。爲了使它打開工具 - >選項 - >設計器,並取消選中「防止保存需要重新創建表的更改」選項...根據您的表大小,您可能也必須設置超時。在此期間你的桌子將被鎖定。
解決這些問題的方法是使用某種序列生成ID。
例如,在SQL Server中,你可以使用下面的命令來創建一個序列:
CREATE SEQUENCE Test.CountBy1
START WITH 1
INCREMENT BY 1 ;
GO
然後在C#中,你可以從測試的檢索下一個值,並將其插入之前分配給該ID。
序列僅在SQL Server 2012中可用; OP正在使用2008年沒有該功能。 – Gabe 2013-03-25 05:03:14
謝謝Gabe,不知道。以下帖子提示「IDENTITY」專欄。 http://stackoverflow.com/questions/7238816/cant-create-sequence-in-sql-server-2008 – 2013-03-25 19:31:50
這聽起來像你想要更高transaction isolation level或更多限制locking。
我不使用這些功能過於頻繁,所以,如果我錯了,希望有人會提出修改建議,但希望其中之一:
-- specify the strictest isolation level
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
insert into XYZ values((SELECT max(ID)+1 from XYZ),'Name')
或
-- make locks exclusive so other transactions cannot access the same rows
insert into XYZ values((SELECT max(ID)+1 from XYZ WITH (XLOCK)),'Name')
好, Java有一個同步關鍵字來防止多個線程互相干擾。我建議你在C#中查找類似結構的多線程鏈接。 – 2013-03-25 04:26:53
@ChetterHummin不,他的問題是他試圖找出在應用程序中插入的ID,當他應該讓數據庫處理它時。是的,他也可以創建共享和同步的ID變量,但這不會阻止數據庫同步的問題。例如,考慮第三方插入到他的表中的問題,該表沒有使用他的共享變量。然後他仍然有同樣的問題。 – KyleM 2013-03-25 04:30:42
@KyleM感謝您的澄清!以上查詢爲 – 2013-03-25 04:31:20