我正在使用SqlBulkCopy
类在表tbl_records
中一次插入50k行
我在此表上设置了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);
但执行前后。它只触发50k插入的First
行
我想它应该为每一行开火。我怎么能这样做?
答案 0 :(得分:8)
触发器永远不会每行触发。它们为相应的DML语句的所有行触发。重写您的触发器,以便它可以处理包含许多行的INSERTED
表。无论如何,这是最佳实践和必修课。
它只触发了从50k行插入的第一行
你必须误解情况,可能是因为你不知道触发器可以在虚拟表中包含多行。
答案 1 :(得分:4)
默认情况下,SqlBulkCopy对象的批量大小是完整的行集。
以下是MSDN对BatchSize属性值的说法: “零(默认值)表示每个WriteToServer操作都是一个批处理。”
在这种情况下,触发器将触发一次,但Inserted表将包含所有受影响记录的条目。
答案 2 :(得分:4)
如果其他人遇到此问题并寻求解决方案,我也会在这里发布我的发现。
重要:usr已经给出了答案,但我会稍作解释。
首先,这就是Microsoft documentation关于批量插入的说法,
如果未指定FIRE_TRIGGERS,则不会执行插入触发器。
FIRE_TRIGGERS指定在 在批量导入操作期间执行目标表。如果 触发器是为目标表上的INSERT操作定义的,它们 每个完成的批次都会被解雇。
FIRE_TRIGGERS
是与BULK INSERT
T-SQL语句一起使用的参数。
如果您尝试对SqlBulkCopy
类(.Net Framework / Core)使用批量插入,则必须使用SqlBulkCopyOptions
枚举(docs)。
当您构造一个A时可以使用SqlBulkCopyOptions枚举 SqlBulkCopy实例更改该方法的WriteToServer方法 实例行为。
这是一个样本,
var options = SqlBulkCopyOptions.CheckConstraints | SqlBulkCopyOptions.FireTriggers | SqlBulkCopyOptions.KeepIdentity;
var bulkCopy = new SqlBulkCopy(connectionString, options);
好。现在触发器将与批量插入一起运行,但是为什么只有一条记录。再次阅读Microsoft关于FIRE_TRIGGER
参数的说法。
如果为目标表上的INSERT操作定义了触发器, 每个完成的批次都会被解雇。
这意味着您的触发器将一次运行整个批次。但是您的批次包含多个行。因此,您的触发算法(您应该对一条记录执行的操作)将只适用于一条记录,而不适用于所有记录。
现在您知道了为什么它不适用于所有人,因此解决方案是改善触发器以处理多行。这意味着迭代抛出INSERTED
临时表附带的所有行,并对所有记录执行算法。您可以使用CURSOR
或简单的WHILE LOOP
。由你决定。
您可以找到示例here。
答案 3 :(得分: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