【问题标题】:Merge and Trigger - Primary Key Violation合并和触发 - 主键违规
【发布时间】:2012-07-19 11:00:59
【问题描述】:

我有那些桌子

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

table test_2 为空,test 有这条记录

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 行 违反主键“PK_Test_2”。无法插入重复键 将值 (1) 放入“Test_2”。

当使用多行调用合并操作时可能会发生这种情况,而不是在 INSERT 和下一个 UPDATE 操作之前调用,它为记录 1 和 2 运行两个 INSERT。 有什么办法?

【问题讨论】:

    标签: sql-server tsql triggers merge-replication


    【解决方案1】:

    解决这个问题的简单方法是在 key 上使用 group by 指令,在 values 上使用聚合函数来求和,如下所示:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-22
      • 2011-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多