2013-04-22 28 views
-1

假設我有我的數據庫中3個表是這樣的:如何在交易完成前使用標識列值?

  • Personpersonid,...)---這是實體,personid是標識列
  • Phonephoneid,...) - - 這是實體,phoneid是標識列
  • PersonPhonepersonid, phoneid)---這種關係

當我插入數據INT o表,我需要先插入實體表中的行並獲取生成的id,然後我需要在關係表中插入一行。

它工作正常。問題是:我有一個交易的存儲過程Try Catch語句,如:

BEGIN TRY 
declare aCursor cursor local fast_forward for (Select Query...) 

open aCursor; 
fetch next from aCursor into @variables.... 

while @@fetch_status = 0 
begin 

    INSERT INTO Person(...); 
    set @personid [email protected]@IDENTITY; 

    INSERT INTO Phone(...); 
    set @phoneid [email protected]@IDENTITY; 

    INSERT INTO PersonPhone(@personid, @phoneid);  
end; 

END TRY 
BEGIN CATCH 
    close aCursor; 
    deallocate selectdistributor; 
    SELECT ERROR_NUMBER() AS ErrorNumber,ERROR_MESSAGE() AS ErrorMessage;  
    ROLLBACK TRAN; 
    RETURN; 
END CATCH 
COMMIT; 
close aCursor; 
deallocate aCursor; 

隨着光標,還有更多的是一個記錄將被插入人的電話。運行SP時,它將停止首次插入關係數據。我也可以正確使用@personid,@phoneid,但在事務完成之前,我在INSERT INTO PersonPhone(@personid,@phoneid)上出錯。如:

INSERT語句與FOREIGN KEY約束「Person_PersonPhone_FK1」衝突。衝突發生在數據庫「MYDB」,表「dbo.Person」,列'PersonID'中。

看起來像系統生成的系統在事務完成之前未被識別。

如何解決此問題?

+0

您是否嘗試過使用'SCOPE_IDENTITY()'?你真的應該忘記存在'@@ IDENTITY'。很可能你有觸發器人或電話,你沒有得到你認爲你得到的ID值 – 2013-04-22 18:48:44

+0

另外,你能解釋你的SELECT查詢如何識別一個特定的人屬於一個特定的手機嗎?(我認爲有一個更有效的方法在沒有所有光標的情況下做到這一點。)第三表的目的是什麼似乎比這更簡單的關係(人<->電話真的多對多?)。 – 2013-04-22 18:56:32

+0

非常感謝。我在桌上有觸發器。將@@ Identity更改爲Scope_Identity()後,不再有錯誤,但沒有插入任何記錄! – KentZhou 2013-04-22 19:04:15

回答

0

可能你的問題在於你使用了@@標識,這個標識不應該被用於這個目的。如果其中一個表具有觸發器,則可能會返回錯誤的值(觸發器插入的表的標識),並且該外鍵鏈接到的表中不存在該值。

因此,假設你有一個觸發onteh第一個表,插入到具有身份的審計表。記錄插入的ID爲1234.如果tirigger插入到不同的表中,則@@ Identity返回的值爲5678,不存在inteh原始表。當您將FK插入到第一張表上時,您會收到錯誤消息,因爲值5678在第一個表中不存在。

改爲使用OUTPUT子句。你也可以使用scope_identity(),但輸出更加靈活(並且可以讓你執行多個記錄插入並接收所有身份以及可能唯一標識記錄的其他字段。

而且我和Aaron ,除非有人威脅我的生活,否則我不會使用光標指示這一點。

相關問題