5

我正在使用SqlBulkCopy类在表中一次插入 50k 行tbl_records 我已经在该表上设置了After Insert触发器并使用以下代码

SqlBulkCopy SqlBc1 = new SqlBulkCopy(strConnString, SqlBulkCopyOptions.FireTriggers);

// Set DataReader For SqlBulkCopy

sqlComm = new SqlCommand(strQuery, sqlTemCon);
sqlComm.CommandTimeout = 3600000;
sqlComm.CommandType = System.Data.CommandType.Text;
SqlDataReader dReader = sqlComm.ExecuteReader();       
SqlBc1.WriteToServer(dReader);

但在执行编后。它仅触发First 插入的 50k 行中的触发

我希望它应该为每一行触发。我怎样才能做到这一点??

4

4 回答 4

9

触发器永远不会按行触发。它们针对相应 DML 语句的所有行触发。重写您的触发器,以便它可以处理INSERTED包含许多行的表。无论如何,这是最佳实践和必需的实践。

它仅触发 50k 行中插入的第一行的触发器

您一定是误解了这种情况,可能是因为您不知道触发器可以在虚拟表中包含多行。

于 2013-09-25T11:01:38.847 回答
4

默认情况下,SqlBulkCopy 对象的批量大小是完整的行集。

以下是 MSDN 关于 BatchSize 属性值的说明:“零(默认值)表示每个 WriteToServer 操作都是一个批处理。”

在这种情况下,触发器将触发一次,但 Inserted 表将包含所有受影响记录的条目。

于 2013-09-25T11:04:08.710 回答
4

如果另一个人遇到这个问题并寻找解决方案,我也会在这里发布我的发现。

重要提示: usr 已经给出了答案,但我会稍微解释一下。

首先,这是微软文档中关于批量插入的内容,

如果未指定 FIRE_TRIGGERS,则不执行插入触发器。

FIRE_TRIGGERS 指定在目标表上定义的任何插入触发器在大容量导入操作期间执行。如果为目标表上的 INSERT 操作定义了触发器,则会为每个完成的批处理触发它们。

FIRE_TRIGGERS是与BULK INSERTT-SQL 语句一起使用的参数。

如果您尝试将批量插入与SqlBulkCopy类(.Net Framework/Core)一起使用,则必须使用SqlBulkCopyOptionsEnum(文档)。

您可以在构造 SqlBulkCopy 实例时使用 SqlBulkCopyOptions 枚举来更改该实例的 WriteToServer 方法的行为方式。

这是一个示例,

var options = SqlBulkCopyOptions.CheckConstraints | SqlBulkCopyOptions.FireTriggers | SqlBulkCopyOptions.KeepIdentity;
var bulkCopy = new SqlBulkCopy(connectionString, options);

好的。现在触发器将使用批量插入运行,但为什么只针对一条记录。再次阅读微软所说的FIRE_TRIGGER争论。

如果为目标表上的 INSERT 操作定义了触发器,则会为每个完成的批处理触发它们。

这意味着,您的触发器将一次运行整个批次。但是您的批次包含不止一行。因此,您的触发算法(您应该对单个记录执行的操作)将适用于一条记录,而不适用于所有记录。

现在您知道为什么它不适用于所有人,因此解决方案是改进您的触发器以处理多行。这意味着迭代抛出所有行带有INSERTED临时表并为所有记录执行您的算法。您可以使用CURSOR或简单的WHILE LOOP. 由你决定。

您可以在此处找到示例。

于 2020-02-19T18:34:54.610 回答
0

我试过这个,它会工作的。

我希望它对你有帮助..

CREATE TRIGGER Triggername ON TableName After INSERT AS SET NOCOUNT ON;

insert into TargetTable (Fields) SELECT (i.field1,i.field2,i.field3,....,i.fieldn) FROM inserted i GO

于 2016-02-23T12:38:48.480 回答