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'),并将它们记录到一个单独的表中。我还需要捕获表名,因为我将在多个表上使用相同的触发器。作为新手,我正在寻找一些帮助来重写触发器,以说明所有受影响的行。“我们不建议在触发器中使用游标,因为它们可能会降低性能。要设计影响多行的触发器,请使用基于行集的逻辑,而不是游标。”