SQL 批量复制:触发器未被触发
SQL bulk copy : Trigger not getting fired
我正在使用 sql 批量复制将数据从 Table1 复制到 Table2 table。我在 Table2 上应用了触发器,但我的触发器并没有在每一行上触发。这是我的触发器和 sqlbulkcopy 函数。
SqlConnection dstConn = new SqlConnection(ConfigurationManager.ConnectionStrings["Destination"].ConnectionString);
string destination = dstConn.ConnectionString;
//Get data from Source in our case T1
DataTable dataTable = new Utility().GetTableData("Select * From [db_sfp_ems].[dbo].[tbl_current_data_new] where [start_date]>'" + calculate_daily_Time + "' and status=0" , source);
SqlBulkCopy bulkCopy = new SqlBulkCopy(source, SqlBulkCopyOptions.FireTriggers)
{
//Add table name of source
DestinationTableName = "tbl_current_data",
BatchSize = 100000,
BulkCopyTimeout = 360
};
bulkCopy.WriteToServer(dataTable);
//MessageBox.Show("Data Transfer Succesfull.");
dstConn.Close();
------触发器-----
ALTER TRIGGER [dbo].[trgAfterInsert] ON [dbo].[tbl_current_data]
AFTER INSERT
AS
BEGIN
declare @intime datetime
declare @sdp_id numeric
declare @value numeric(9,2)
SELECT @intime= DATEADD(SECOND, -DATEPART(SECOND, start_date), start_date) FROM INSERTED
SELECT @sdp_id= sdp_id FROM INSERTED
SELECT @value= value FROM INSERTED
INSERT INTO Table3(sdp_id,value,start_date)
VALUES
(
@sdp_id,@value,@intime
)
触发器在插入后触发,插入是否涉及 0、1 或多条记录对触发器没有影响。因此,即使您要插入一大堆记录,触发器也只会触发一次。这是设计使然,并非特定于 BULK_INSERT
;每种插入都是如此。这也意味着 inserted
伪 table 可以保存 0、1 或多个记录。这是一个常见的陷阱。请务必以可以处理多个记录的方式编写触发器。例如:如果 inserted
包含多个记录,SELECT @sdp_id= sdp_id FROM INSERTED
将不会按预期工作。变量将被设置,但您无法知道它将保留什么值(来自插入的记录)。
这是 SQL 基于集合的哲学的全部内容,最好不要尝试使用循环或其他 RBAR 方法来破坏该哲学。保持固定的心态。
你的扳机坏了。在 SQL 服务器中,触发器一次处理多行。假设 inserted
有一行是致命错误——我希望它会导致语法错误。
我想这就是你想要的代码:
ALTER TRIGGER [dbo].[trgAfterInsert] ON [dbo].[tbl_current_data]
AFTER INSERT
AS
BEGIN
INSERT INTO Table3 (sdp_id, value, start_date)
SELECT sdp_id, value,
DATEADD(SECOND, -DATEPART(SECOND, start_date), start_date)
FROM inserted i;
END;
除了正确之外,还有一个优点就是代码写起来比较简单
注意:您正在将 "seconds" 部分设置为 0。但是,根据类型的不同,start_date
可能还有小数秒。如果这是一个问题,请提出另一个问题。
我正在使用 sql 批量复制将数据从 Table1 复制到 Table2 table。我在 Table2 上应用了触发器,但我的触发器并没有在每一行上触发。这是我的触发器和 sqlbulkcopy 函数。
SqlConnection dstConn = new SqlConnection(ConfigurationManager.ConnectionStrings["Destination"].ConnectionString);
string destination = dstConn.ConnectionString;
//Get data from Source in our case T1
DataTable dataTable = new Utility().GetTableData("Select * From [db_sfp_ems].[dbo].[tbl_current_data_new] where [start_date]>'" + calculate_daily_Time + "' and status=0" , source);
SqlBulkCopy bulkCopy = new SqlBulkCopy(source, SqlBulkCopyOptions.FireTriggers)
{
//Add table name of source
DestinationTableName = "tbl_current_data",
BatchSize = 100000,
BulkCopyTimeout = 360
};
bulkCopy.WriteToServer(dataTable);
//MessageBox.Show("Data Transfer Succesfull.");
dstConn.Close();
------触发器-----
ALTER TRIGGER [dbo].[trgAfterInsert] ON [dbo].[tbl_current_data]
AFTER INSERT
AS
BEGIN
declare @intime datetime
declare @sdp_id numeric
declare @value numeric(9,2)
SELECT @intime= DATEADD(SECOND, -DATEPART(SECOND, start_date), start_date) FROM INSERTED
SELECT @sdp_id= sdp_id FROM INSERTED
SELECT @value= value FROM INSERTED
INSERT INTO Table3(sdp_id,value,start_date)
VALUES
(
@sdp_id,@value,@intime
)
触发器在插入后触发,插入是否涉及 0、1 或多条记录对触发器没有影响。因此,即使您要插入一大堆记录,触发器也只会触发一次。这是设计使然,并非特定于 BULK_INSERT
;每种插入都是如此。这也意味着 inserted
伪 table 可以保存 0、1 或多个记录。这是一个常见的陷阱。请务必以可以处理多个记录的方式编写触发器。例如:如果 inserted
包含多个记录,SELECT @sdp_id= sdp_id FROM INSERTED
将不会按预期工作。变量将被设置,但您无法知道它将保留什么值(来自插入的记录)。
这是 SQL 基于集合的哲学的全部内容,最好不要尝试使用循环或其他 RBAR 方法来破坏该哲学。保持固定的心态。
你的扳机坏了。在 SQL 服务器中,触发器一次处理多行。假设 inserted
有一行是致命错误——我希望它会导致语法错误。
我想这就是你想要的代码:
ALTER TRIGGER [dbo].[trgAfterInsert] ON [dbo].[tbl_current_data]
AFTER INSERT
AS
BEGIN
INSERT INTO Table3 (sdp_id, value, start_date)
SELECT sdp_id, value,
DATEADD(SECOND, -DATEPART(SECOND, start_date), start_date)
FROM inserted i;
END;
除了正确之外,还有一个优点就是代码写起来比较简单
注意:您正在将 "seconds" 部分设置为 0。但是,根据类型的不同,start_date
可能还有小数秒。如果这是一个问题,请提出另一个问题。