2012-07-19 93 views
1

我有這些表合併和觸發 - 主鍵衝突

CREATE TABLE [Test](
    [Id] [int] NOT NULL, 
    [Value] [int] NOT NULL, 
    [Id_Test_2] [int] NOT NULL, 
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 



CREATE TABLE [Test_2](
    [Id_Test_2] [int] NOT NULL, 
    [Value_Test_2] [int] NOT NULL, 
CONSTRAINT [PK_Test_2] PRIMARY KEY CLUSTERED 
(
    [Id_Test_2] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

桌子上的測試,我有此更新觸發:

CREATE TRIGGER [dbo].[Test_TriggerUpdate] 
ON [dbo].[Test] 

FOR UPDATE 

NOT FOR REPLICATION 

AS 
BEGIN 

MERGE Test_2 AS Target 

    USING 
     (SELECT D.Id_Test_2 , 
        (COALESCE(D.Value, 0) * 2) AS Value 
      FROM  Deleted D      
     ) AS Source 
    ON (Target.Id_Test_2 = Source.Id_Test_2  ) 
    WHEN MATCHED 
     THEN 
      UPDATE 
      SET    TARGET.Value_Test_2 = (TARGET.Value_Test_2 - Source.Value) 
    WHEN NOT MATCHED BY TARGET 
     THEN 
     INSERT (
         Id_Test_2 , 
         Value_Test_2 

        ) 
      VALUES (Source.Id_Test_2 ,      
         (Source.[Value]*(-1)) 
        ); 



    MERGE Test_2 AS Target 
    USING 
     (SELECT I.Id_Test_2 , 
        (COALESCE(I.Value, 0) 
         * 2) AS Value 
      FROM  INSERTED I 
     ) AS Source 
    ON (Target.Id_Test_2 = Source.Id_Test_2 
     ) 
    WHEN MATCHED 
     THEN 
      UPDATE 
      SET    TARGET.Value_Test_2 = (TARGET.Value_Test_2 + Source.Value) 
    WHEN NOT MATCHED BY TARGET 
     THEN 
     INSERT (
         Id_Test_2 , 
         Value_Test_2 

        ) 
      VALUES (Source.Id_Test_2 , 
         Source.[Value] 
        ); 

END 

表test_2是空的,測試有此記錄

Id Value Id_Test_2 
1 10 1 
2 20 1 
3 30 2 

當我運行此更新

UPDATE Test SET VALUE= 50 

我有這種錯誤

消息2627,級別14,狀態1,過程Test_TriggerUpdate的,12號線 違反PRIMARY KEY 'PK_Test_2'。不可能將具有值(1)的重複鍵 插入'Test_2'中。

也許這種情況發生時,合併操作調用multirows和,而不是INSERT之前調用,下一次更新操作,運行兩個INSERT備案1和2 什麼是可以做的?

回答

1

來解決這個問題的簡單方法是使用組的指令通過對密鑰和值的聚集函數來概括,因爲這:

ALTER TRIGGER [dbo].[Test_TriggerUpdate] 
ON [dbo].[Test] 

FOR UPDATE 

NOT FOR REPLICATION 

AS 
BEGIN 

    MERGE Test_2 AS Target 
    USING 
     (SELECT D.Id_Test_2 , 
        sum((COALESCE(D.Value, 0) * 2)) AS Value 
      FROM  Deleted D  
      GROUP BY Id_Test_2 
     ) AS Source 
    ON (Target.Id_Test_2 = Source.Id_Test_2) 
    WHEN MATCHED 
     THEN 
     UPDATE 
      SET TARGET.Value_Test_2 = (TARGET.Value_Test_2 - Source.Value) 
    WHEN NOT MATCHED BY TARGET 
     THEN 
     INSERT (Id_Test_2 , 
        Value_Test_2 
       ) 
     VALUES (Source.Id_Test_2 , 
        (Source.[Value]*(-1)) 
       ); 

    MERGE Test_2 AS Target 
    USING 
     (SELECT I.Id_Test_2 , 
        sum((COALESCE(I.Value, 0) * 2)) AS Value 
      FROM  INSERTED I 
      GROUP BY Id_Test_2 
     ) AS Source 
    ON (Target.Id_Test_2 = Source.Id_Test_2) 
    WHEN MATCHED 
     THEN 
     UPDATE 
      SET TARGET.Value_Test_2 = (TARGET.Value_Test_2 + Source.Value) 
    WHEN NOT MATCHED BY TARGET 
     THEN 
     INSERT (Id_Test_2 , 
        Value_Test_2 
       ) 
     VALUES (Source.Id_Test_2 , 
        Source.[Value] 
       ); 

END