【问题标题】:Sql update query doesn't fire update trigger for all recordsSql 更新查询不会触发所有记录的更新触发器
【发布时间】:2018-09-28 15:54:14
【问题描述】:

我从 table1 触发器调用了更新查询,当该查询运行时,它成功更新了其他 table2,但 table2 的更新触发器仅触发了 1 次,这意味着不是针对从更新查询更新的每条记录

我使用的是 SQL Server 2008 Express 版本-

请指点我哪里错了

【问题讨论】:

  • 能否提供更多信息,代码,表结构
  • 对于所有受影响的记录,每个 UPDATE、INSERT 或 DELETE 命令都会调用一次触发器。虚拟表 INSERTED 和 DELETED 如果多条记录受该命令影响,将有多条记录。
  • 我已经在答案中展示了我的第一个更新触发器,您可以在其中看到,更新查询成功运行并按预期更新所有记录,但是除了第一条记录之外的所有记录都不会触发 2table 的更新触发器。
  • 马尔科夫,我已经发布了第二个答案,我通过在触发器中使用光标而不是更新查询来实现我想要的结果。一切正常。但问题是我不想使用游标,所以我替换我的游标来设置基于更新查询的方法。
  • @DavidDubois,正如你所说,触发器为每个更新命令调用一次,你的意思是,不是所有通过更新查询更新的行?因为您知道 sql 是基于设置的方法,所以可以通过单个命令一次更新多条记录。

标签: sql sql-server triggers sql-update sql-server-2008-express


【解决方案1】:

终于得到了答案:/,触发器触发一次以执行单个查询。批量或批量更新/插入/删除不会唤醒每一行的触发器 :(,我非常感谢 Markov 先生和 David Dubois 先生,他们有兴趣帮助我:) 谢谢亲爱的,

【讨论】:

    【解决方案2】:
    ALTER TRIGGER [dbo].[tbl_Inv_PurchaseNoteDetailUpdate] 
       ON  [dbo].[tbl_Inv_PurchaseNoteDetail] 
       AFTER Update
    AS 
    BEGIN
        SET NOCOUNT ON;
    
    Declare @RefNo as varchar(15) Declare @rate as float 
    Declare @NewNetValue as float Declare @OldNetValue as float
    
    select
    @RefNo=ReferenceNo,
    @rate=Rate
    from inserted 
    
    
    select 
    @NewNetValue=isnull(i.NetAmount,0), @OldNetValue=isnull(d.NetAmount,0)
    from inserted i inner join deleted d on i.id = d.id  
    
     --if amount changes then rate should be updated to another table 
    if  @NewNetValue<>@OldNetValue 
    begin
        -- using cursor work fine, update trigger of table[tbl_Inv_Ledger] is fired for every record
        Declare @Inv_LedgerID as numeric
        DECLARE  PurchaseNoteDetail_Cursor  CURSOR FOR
        Select ID from dbo.tbl_Inv_Ledger where ReferenceNo=@ReferenceNo 
        and FK_tbl_Inv_PurchaseNoteDetail_ID is null 
        and FK_tbl_Inv_PurchaseReturnNoteDetail_ID is null -- also check purchase return entry should not be distrubed
    
        OPEN  PurchaseNoteDetail_Cursor
        FETCH NEXT FROM  PurchaseNoteDetail_Cursor INTO @Inv_LedgerID
        WHILE @@FETCH_STATUS = 0
        BEGIN
    
        update dbo.tbl_Inv_Ledger
        set Rate=@Rate
        where ID=@Inv_LedgerID
    
        FETCH NEXT FROM  PurchaseNoteDetail_Cursor INTO @Inv_LedgerID
        END
        CLOSE   PurchaseNoteDetail_Cursor
        DEALLOCATE   PurchaseNoteDetail_Cursor 
    end     
     -----------------xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-----------------
    END
    

    【讨论】:

    • 通过使用游标,按预期工作,意味着对所有更新的记录触发第二个表的更新触发器。但不想使用光标,所以请帮助我
    【解决方案3】:

    这是触发并使用更新查询更新另一个表的触发器,但没有为除已更新的第二个表的第一条记录之外的所有记录触发更新触发器。

        ALTER TRIGGER [dbo].[tbl_Inv_PurchaseNoteDetailUpdate] 
           ON  [dbo].[tbl_Inv_PurchaseNoteDetail] 
           AFTER Update
        AS 
        BEGIN
            SET NOCOUNT ON;
    
        Declare @RefNo as varchar(15) Declare @rate as float 
        Declare @NewNetValue as float Declare @OldNetValue as float
    
        select
        @RefNo=ReferenceNo,
        @rate=Rate
        from inserted 
    
    
        select 
        @NewNetValue=isnull(i.NetAmount,0), @OldNetValue=isnull(d.NetAmount,0)
        from inserted i inner join deleted d on i.id = d.id  
    
         --if amount changes then rate should be updated to another table 
        if  @NewNetValue<>@OldNetValue 
        begin
    
            ---this will update new rate in table[tbl_Inv_Ledger] 
            --but didnot fire update trigger of table[tbl_Inv_Ledger] for all record which was updated
        update dbo.tbl_Inv_Ledger
        set Rate=Rate
        where ReferenceNo=@RefNo
        ---update trigger of table[tbl_Inv_Ledger] is fired only for first record
        end     
    
    end
    

    【讨论】:

    • 这是设置的基本方法,其中第二个表的所有记录都已成功更新,但不幸的是,第二个表的更新触发器会针对已更新的第一条记录触发 [即不是针对已更新的每条记录]: (
    猜你喜欢
    • 2013-06-11
    • 2017-07-22
    • 1970-01-01
    • 2017-02-16
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    相关资源
    最近更新 更多