Sql server 用于处理多行插入和更新的触发器
我使用以下触发器跟踪多个表上的插入和更新,并将其记录在日志表中Sql server 用于处理多行插入和更新的触发器,sql-server,triggers,Sql Server,Triggers,我使用以下触发器跟踪多个表上的插入和更新,并将其记录在日志表中 CREATE TRIGGER tr_TestTable1] ON [TestTable_1] AFTER INSERT, UPDATE AS DECLARE @keyid int, @tn nvarchar(50), @recEditMode nvarchar(50), @trstat nvarchar(50) BEGIN SET NOCOUNT ON; SET @tn = 'TestTable_1'
CREATE TRIGGER tr_TestTable1]
ON [TestTable_1]
AFTER INSERT, UPDATE
AS
DECLARE @keyid int, @tn nvarchar(50), @recEditMode nvarchar(50), @trstat nvarchar(50)
BEGIN
SET NOCOUNT ON;
SET @tn = 'TestTable_1'
IF EXISTS(SELECT 1 FROM INSERTED)
BEGIN
SET @recEditMode = (Select REC_EDIT_MODE FROM inserted)
SET @trstat = 'PENDING'
SET @keyid = (Select prkeyId FROM inserted)
IF (@recEditMode = 'MANUAL')
BEGIN
IF NOT EXISTS (SELECT * FROM [logTable_1] WHERE SourceKeyId = @keyid AND TrStatus = 'PENDING' AND SourceTableName = @tn)
BEGIN
INSERT INTO [logTable_1](SourceKeyId,SourceTableName,TrStatus)
VALUES (@keyid, @tn, @trstat)
END
END
END
END
这在单行插入和单行更新上非常有效。我无法优化此代码以处理多行插入和更新。正在寻找处理此问题的帮助
谢谢。我对触发器进行了如下修改,现在似乎工作正常
CREATE TRIGGER tr_TestTable1]
ON [TestTable_1]
AFTER INSERT, UPDATE
AS
DECLARE @keyid int, @tn nvarchar(50), @trstat nvarchar(50)
BEGIN
IF @@ROWCOUNT = 0
RETURN
SET NOCOUNT ON;
IF EXISTS(SELECT * FROM INSERTED)
BEGIN
SET @tn = 'TestTable_1'
SET @trstat = 'PENDING'
BEGIN
INSERT INTO LogTable_1 (SourceKeyId, SourceTableName, TrStatus)
SELECT I.prKeyId, @tn, @trStat FROM INSERTED AS I
WHERE (I.REC_EDIT_MODE = 'MANUAL' AND NOT EXISTS(SELECT * FROM LogTable_1 WHERE SourceKeyId = I.prKeyId AND SourceTableName = @tn AND TrStatus = 'PENDING'))
END
END
END
我修改了触发器如下,它现在似乎工作良好
CREATE TRIGGER tr_TestTable1]
ON [TestTable_1]
AFTER INSERT, UPDATE
AS
DECLARE @keyid int, @tn nvarchar(50), @trstat nvarchar(50)
BEGIN
IF @@ROWCOUNT = 0
RETURN
SET NOCOUNT ON;
IF EXISTS(SELECT * FROM INSERTED)
BEGIN
SET @tn = 'TestTable_1'
SET @trstat = 'PENDING'
BEGIN
INSERT INTO LogTable_1 (SourceKeyId, SourceTableName, TrStatus)
SELECT I.prKeyId, @tn, @trStat FROM INSERTED AS I
WHERE (I.REC_EDIT_MODE = 'MANUAL' AND NOT EXISTS(SELECT * FROM LogTable_1 WHERE SourceKeyId = I.prKeyId AND SourceTableName = @tn AND TrStatus = 'PENDING'))
END
END
END
这是用于哪个RDBMS的?对于触发器,无论您使用的是MySQL、PostgreSQL、Oracle、SQL Server还是IBM DB2,甚至是其他什么,都会产生巨大的差异。请在您的问题中添加相关标签!如果这是针对SQL Server的,那么您的触发器有一个主要缺陷:您假设它每行调用一次—事实并非如此。每个语句触发一次触发器,因此如果
INSERT
语句插入25行,则触发器触发一次,而Inserted
伪表将包含25行。您的代码将在此处选择这25行中的哪一行<代码>从插入的中选择prkeyId-这是不确定的,您将得到一个任意行,并将忽略所有其他行。你需要重写你的触发器来考虑这一点!对不起,信息不完整。数据库是SQL Server,我意识到触发器将按语句触发。我试图跟踪所有符合特定条件的行(recEditMode='MANUAL'),并将它们记录到一个单独的表中。我还需要捕获表名,因为我将在多个表上使用相同的触发器。作为新手,我一直在寻找一些帮助来重写触发器,以说明所有受影响的行。“我们不建议在触发器中使用游标,因为它们可能会降低性能。要设计影响多行的触发器,请使用基于行集的逻辑,而不是游标。”这适用于哪种RDBMS?对于触发器,无论您使用的是MySQL、PostgreSQL、Oracle、SQL Server还是IBM DB2,甚至是其他什么,都会产生巨大的差异。请在您的问题中添加相关标签!如果这是针对SQL Server的,那么您的触发器有一个主要缺陷:您假设它每行调用一次—事实并非如此。每个语句触发一次触发器,因此如果INSERT
语句插入25行,则触发器触发一次,而Inserted
伪表将包含25行。您的代码将在此处选择这25行中的哪一行<代码>从插入的中选择prkeyId-这是不确定的,您将得到一个任意行,并将忽略所有其他行。你需要重写你的触发器来考虑这一点!对不起,信息不完整。数据库是SQL Server,我意识到触发器将按语句触发。我试图跟踪所有符合特定条件的行(recEditMode='MANUAL'),并将它们记录到一个单独的表中。我还需要捕获表名,因为我将在多个表上使用相同的触发器。作为新手,我正在寻找一些帮助来重写触发器,以说明所有受影响的行。“我们不建议在触发器中使用游标,因为它们可能会降低性能。要设计影响多行的触发器,请使用基于行集的逻辑,而不是游标。”