2015-07-06 66 views
2

我有我的存儲過程的問題:同時從SQL Server 2的INSERT語句返回SCOPE_IDENTITY

CREATE PROCEDURE [dbo].[Project] 
    @Code as nvarChar(255) = null, 
    @Id as nvarChar(255) = null, 
    @Status as nvarChar(max) = null, 
    @Project as nvarChar(max) = null, 
    @ClientSystem as nvarchar(max) = null, 
    @UserId as bigint = 0, 
    @ProjectId as bigint = 0, 
    @ProjectDetailsId bigint = 0 Output 
AS 
    SET NOCOUNT OFF; 

    IF NOT EXISTS (SELECT [Code] 
        FROM [dbo].[Project] 
        WHERE Project.Code = @Code) 
    BEGIN 
     INSERT INTO [dbo].[Project]([Code], [Id], [Status], [Project]) 
     VALUES(@Code, @Id, @Status, @Project) 

     SELECT @ProjectId = SCOPE_IDENTITY() 

     INSERT INTO [dbo].[ProjectDetails]([FK_ProjectId], [ClientSystem], [UserId]) 
     VALUES(@ProjectId, @ClientSystem, @UserId) 

     SELECT @ProjectDetailsId = SCOPE_IDENTITY() 
    END 
    ELSE 
    BEGIN 
     SELECT [ProjectId] AS 'ProjectId' 
     FROM [dbo].[Project] 
     WHERE Project.Code = @Code 
    END 

我要回來自Insert聲明Scope_Identity並通過第一次插入的值作爲參數傳遞給第二插入並返回2nd Insert語句的Scope_Identity

我得到的錯誤是當我得到的第一個Insert的身份,在特定表中的身份增加2倍,如在數據庫表中它將被插入2但在編碼它將返回1。給其他插入它給予衝突。

+0

你的代碼看起來確定我要插入不同的是你的'@ProjectId因爲bigint = 0,'不是'輸出'參數 – ughai

+0

非常好的問題,upvote –

+0

@ughai不,這不是原因。原因是'SCOPE_IDENTITY()'返回最後一個插入的值,而不管它發生在何處。因此,當第二個插入正在運行** parallel **時,對'SCOPE_IDENTITY()'的調用將從另一個並行運行過程返回值。 –

回答

1

解決方案:而不是使用SCOPE IDENTITY()的,你需要利用他的INSERT聲明OUTPUT條款,如:

INSERT INTO [dbo].[Project]([Code], [Id], [Status], [Project]) 
OUTPUT inserted.ID into @ProjectID 
SELECT ... 

說明:SCOPE_IDENTITY()返回上次insert的價值,無論插入發生在何處。所以,當另一個insert並行中運行時,那麼您撥打SCOPE_IDENTITY()將返回其他並行運行程序的值。這會導致錯誤。

但是,OUTPUT子句的用法將保證返回值從當前INSERT

下面是關於SCOPE_IDENTITY和並行策略一篇有趣的文章: http://blog.sqlauthority.com/2009/03/24/sql-server-2008-scope_identity-bug-with-multi-processor-parallel-plan-and-solution/

+0

@SeanLange你錯了。即使Pinal Dave兩年後也糾正了自己。 http://blog.sqlauthority.com/2009/03/24/sql-server-2008-scope_identity-bug-with-multi-processor-parallel-plan-and-solution/ –

+0

嗯有趣。 6年,不知何故,我設法錯過了這一個。我立場糾正,將刪除我以前的錯誤陳述。我會收回我的downvote,但不能編輯答案。 –

+0

@SeanLange好的!如果你刪除了downvote,那也會很好;)我記得我自己超出了問題的範圍,有些觸發器產生了錯誤。但現在不知道細節。 –

0

您需要使用OUTPUT子句在過程參數

@ProjectId as bigint = 0 output, 
+0

不,那不是原因。原因是'SCOPE_IDENTITY()'返回最後一個插入的值,而不管它發生在何處。因此,當第二個插入正在運行** parallel **時,對'SCOPE_IDENTITY()'的調用將從另一個並行運行過程返回值。 –