多次插入后使用触发器更新日志table
Use trigger after multiple insert to update log table
我有以下触发器:
ALTER TRIGGER [Staging].[tr_UriData_ForInsert]
ON [Staging].[UriData]
FOR INSERT
AS
BEGIN
DECLARE @_Serial NVARCHAR(50)
DECLARE @_Count AS INT
IF @@ROWCOUNT = 0
RETURN
SET NOCOUNT ON;
IF EXISTS(SELECT * FROM inserted)
BEGIN
SELECT @_Count = COUNT(Id) FROM inserted
SELECT @_Serial = SerialNumber FROM inserted
INSERT INTO [Staging].[DataLog]
VALUES (CURRENT_TIMESTAMP, @_Serial + ': Data Insert --> Rows inserted: ' + @_Count, 'New data has been received')
END
END
table 一次接收多行。我希望能够在日志中添加一行 table 来告诉我插入已经发生。
插入一行时效果很好,但插入多行时,触发器不会触发。我已经阅读了这里的其他项目,很明显你不应该使用 ROW_NUMBER()
.
总而言之:当在另一个名为 UriData 的 table 中发生多行插入时,我想更新我的日志 table。
使用以下命令从 C# 插入数据:
using (var sqlBulk = new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, transaction))
{
sqlBulk.DestinationTableName = tableName;
try
{
sqlBulk.WriteToServer(dt);
}
catch(SqlException sqlEx)
{
transaction.Rollback();
var msg = sqlEx.Message;
return false;
}
finally {
transaction.Commit();
conn.Close();
}
}
我不想知道插入的是什么,但是当它发生时,我可以 运行 一组 SPROCS 来清理和转换数据。
TIA
问题是您的触发器假定只会更新一行。标量变量只能有 1 个值。因此,例如,语句 SELECT @_Serial = SerialNumber FROM inserted
会将 @_Serial
设置为从对象 inserted
.
返回的最后一个值
如实对待您的数据,即数据集。这是未经测试的,但是,我怀疑这会给你想要的结果:
ALTER TRIGGER [Staging].[tr_UriData_ForInsert]
ON [Staging].[UriData]
FOR INSERT
AS
BEGIN
--No need for a ROWCOUNT. If there are no rows, then nothing was inserted, and this trigger won't happen.
INSERT INTO [Staging].[DataLog] ({COLUMNS LIST})
SELECT CURRENT_TIMESTAMP,
SerialNumber + ': Data Insert --> Rows inserted: ' +
CONVERT(varchar(10),COUNT(SerialNumber) OVER (PARTITION BY SerialNumber)), --COUNT returns an INT, so this statement would have failed with a conversion error too
'New data has been received'
FROM inserted;
END
请注意我的评论或括号中的部分 ({}
)。
编辑:肖恩使用了 GROUP BY
,此后删除了他的答案。我复制了你的确切方法,但是,GROUP BY
可能是你想要的子句,而不是 OVER
.
经过大量的挖掘和争论,我的托管公司告诉我他们已经禁用了任何类型的批量插入,而没有费心去通知他们的客户。
我有以下触发器:
ALTER TRIGGER [Staging].[tr_UriData_ForInsert]
ON [Staging].[UriData]
FOR INSERT
AS
BEGIN
DECLARE @_Serial NVARCHAR(50)
DECLARE @_Count AS INT
IF @@ROWCOUNT = 0
RETURN
SET NOCOUNT ON;
IF EXISTS(SELECT * FROM inserted)
BEGIN
SELECT @_Count = COUNT(Id) FROM inserted
SELECT @_Serial = SerialNumber FROM inserted
INSERT INTO [Staging].[DataLog]
VALUES (CURRENT_TIMESTAMP, @_Serial + ': Data Insert --> Rows inserted: ' + @_Count, 'New data has been received')
END
END
table 一次接收多行。我希望能够在日志中添加一行 table 来告诉我插入已经发生。
插入一行时效果很好,但插入多行时,触发器不会触发。我已经阅读了这里的其他项目,很明显你不应该使用 ROW_NUMBER()
.
总而言之:当在另一个名为 UriData 的 table 中发生多行插入时,我想更新我的日志 table。
使用以下命令从 C# 插入数据:
using (var sqlBulk = new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, transaction))
{
sqlBulk.DestinationTableName = tableName;
try
{
sqlBulk.WriteToServer(dt);
}
catch(SqlException sqlEx)
{
transaction.Rollback();
var msg = sqlEx.Message;
return false;
}
finally {
transaction.Commit();
conn.Close();
}
}
我不想知道插入的是什么,但是当它发生时,我可以 运行 一组 SPROCS 来清理和转换数据。
TIA
问题是您的触发器假定只会更新一行。标量变量只能有 1 个值。因此,例如,语句 SELECT @_Serial = SerialNumber FROM inserted
会将 @_Serial
设置为从对象 inserted
.
如实对待您的数据,即数据集。这是未经测试的,但是,我怀疑这会给你想要的结果:
ALTER TRIGGER [Staging].[tr_UriData_ForInsert]
ON [Staging].[UriData]
FOR INSERT
AS
BEGIN
--No need for a ROWCOUNT. If there are no rows, then nothing was inserted, and this trigger won't happen.
INSERT INTO [Staging].[DataLog] ({COLUMNS LIST})
SELECT CURRENT_TIMESTAMP,
SerialNumber + ': Data Insert --> Rows inserted: ' +
CONVERT(varchar(10),COUNT(SerialNumber) OVER (PARTITION BY SerialNumber)), --COUNT returns an INT, so this statement would have failed with a conversion error too
'New data has been received'
FROM inserted;
END
请注意我的评论或括号中的部分 ({}
)。
编辑:肖恩使用了 GROUP BY
,此后删除了他的答案。我复制了你的确切方法,但是,GROUP BY
可能是你想要的子句,而不是 OVER
.
经过大量的挖掘和争论,我的托管公司告诉我他们已经禁用了任何类型的批量插入,而没有费心去通知他们的客户。