【问题标题】:MS SQL trigger not inserting records for bulk insertMS SQL 触发器不为批量插入插入记录
【发布时间】:2020-09-29 12:54:27
【问题描述】:

其中一个外部应用程序正在 SQL Azure 表中插入超过 40K 条记录。

我有一个触发器来处理与不同记录的唯一列值的列值匹配的所有必需行

  1. 每当插入 40K+ 记录时,触发器就无法获取或触发所有记录,有时只能获取 1 条和 2 条记录。

  2. 在触发器中如何获取不同的列值和排序依据。

  1. 插入到临时表中只插入更少的列并且是随机的

如何从批量插入的触发器进行批处理

  /****** Object:  Trigger [dbo].[PriceStagingInsertTrigger]    Script Date: 
    29/09/2020 13:46:24 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO

    ALTER TRIGGER [dbo].[PriceStagingInsertTrigger] on [dbo]. 
    [SalesPriceStaging]
    AFTER INSERT 
    AS DECLARE @ItemNumber NVARCHAR(20),
           @applicablefromdate datetime,
           @partycodetype int

     SELECT @ItemNumber = ins.ITEMNUMBER FROM INSERTED ins;
     SELECT @applicablefromdate = ins.PRICEAPPLICABLEFROMDATE FROM INSERTED ins;
     SELECT @partycodetype = ins.PARTYCODETYPE FROM INSERTED ins;
     SELECT * into #temptables from inserted
     EXEC dbo.spSalesPriceStaging @ItemNumber,@applicablefromdate,@partycodetype

     PRINT 'Stored procedure spSalesPriceStaging executed and completed'

【问题讨论】:

  • “每当插入 40K+ 记录时,触发器就无法获取或触发所有记录,有时只能获取 1 条和 2 条记录。” 因为您的 @987654323 @ 假定 INSERT 只影响 1 行。它们可以影响 1 个或多个...Bad Habits to Kick : Abusing triggers
  • 另外,TRIGGER 应该对 DML 语句的影响尽可能小。执行存储过程很少。
  • 您只能在声明的变量中存储 1 个值,因此您的代码只会将 1 行插入日志消息并执行一次。
  • 就个人而言,我会将执行过程的逻辑移到其他地方。如果需要,让触发器将所需的数据记录到池表中,然后让存储过程由不同的进程执行;可能是常规的计划任务。您可能还需要为基于集合的解决方案重构您的过程,而不是处理多个标量参数。
  • @Larnu Hi ,所以您认为我应该将值最初存储在临时表中并进行处理。由于我是 SQL 触发器的新手,所以我如何确保在批量插入时获得所有记录?除了使用触发器之外,还有其他更好的方法吗? , 因为我的要求是在对所有感兴趣的记录进行批量插入时处理所有记录

标签: sql sql-server azure-sql-server


【解决方案1】:

(坏的)解决方案是:

ALTER TRIGGER [dbo].[PriceStagingInsertTrigger] 
ON [dbo].[SalesPriceStaging]
AFTER INSERT 
AS
SET NOCOUNT ON;
DECLARE @ItemNumber NVARCHAR(20),
           @applicablefromdate datetime,
           @partycodetype int;

DECLARE C CURSOR 
FOR 
   SELECT ITEMNUMBER, PRICEAPPLICABLEFROMDATE, PARTYCODETYPE 
   FROM inserted;
OPEN C;
FETCH C INTO @ItemNumber, @applicablefromdate, @partycodetype;
WHILE @@fetch_status = 0
BEGIN
   EXEC dbo.spSalesPriceStaging @ItemNumber,@applicablefromdate,@partycodetype;
   FETCH C INTO @ItemNumber, @applicablefromdate, @partycodetype;
END;
CLOSE C;
DEALLOCATE C;
GO

正如他们所说,SQL Server 中的触发器具有基于集合的逻辑,即使插入了 3657435435143213213 行,也只会触发一次。

代码中存在变量通常是一种模式,一种糟糕的代码设计......

【讨论】:

    猜你喜欢
    • 2016-01-31
    • 2012-11-12
    • 1970-01-01
    • 1970-01-01
    • 2013-10-05
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    • 2013-06-11
    相关资源
    最近更新 更多