Sql Server触发器触发空表插入和删除

时间:2014-06-12 13:05:51

标签: sql-server

我已在触发的表上定义了一个触发器

AFTER INSERT, DELETE, UPDATE

在某些情况下触发器会触发,INSERTEDDELETED表都为空。怎么可能呢?

对于记录,这是触发器

CREATE TRIGGER [dbo].[AuditUsersTrigger] ON [dbo].[Users]
AFTER INSERT, DELETE, UPDATE
AS 
BEGIN
    SET NOCOUNT ON


    DECLARE @type nchar(1), @hasChanges bit
    SET @hasChanges = 1
    IF EXISTS (SELECT * FROM INSERTED)
        IF EXISTS (SELECT * FROM DELETED)
        BEGIN
            SELECT @type = 'U'

            IF EXISTS (
                SELECT *
                FROM INSERTED i
                INNER JOIN DELETED d ON
                    i.Name = d.Name AND
                    i.Pwd = d.Pwd AND
                    ...
            ) SELECT @hasChanges = 0
        END
        ELSE
            SELECT @type = 'I'
    ELSE
        SELECT @type = 'D'


    IF @type = 'D' OR (@type = 'U' AND @hasChanges = 1)
    BEGIN
        INSERT AuditUsers (
            New, Id, Name, ...
        )
        SELECT
            0, Id, Name, ...
        FROM DELETED

        IF @type = 'D'
        BEGIN
            INSERT AuditUsers (New)
            SELECT 1
        END
    END

    IF @type = 'I' OR (@type = 'U' AND @hasChanges = 1)
    BEGIN
        IF @type = 'I'
        BEGIN
            INSERT AuditUsers (New)
            SELECT 0
        END

        INSERT AuditUsers (
            New, Id, Name, ...
        )
        SELECT
            0, Id, Name, ...
        FROM INSERTED
    END


    IF Trigger_Nestlevel() < 2
    BEGIN
        DECLARE @clientId TABLE (id INT)
        DECLARE @clientCode NVARCHAR(50), @shopId INT;

        IF @type = 'I' OR @type = 'U'
        BEGIN
            SELECT @clientCode = ClientCode, @shopId = ShopId FROM INSERTED;
            INSERT INTO @clientId SELECT id FROM Clients WHERE code = @clientCode;

            IF NOT EXISTS (SELECT 1 FROM @clientId)
            BEGIN
                INSERT Clients (name, code, active, shopId) OUTPUT INSERTED.id INTO @clientId
                VALUES (@clientCode, @clientCode, 1, @shopId);
            END


            UPDATE Users SET ClientId = (SELECT TOP 1 id FROM @clientId) WHERE ClientCode = @clientCode;
        END
    END
END

1 个答案:

答案 0 :(得分:6)

这是documented behaviour

  

当用户尝试通过数据操纵语言(DML)事件修改数据时,DML触发器执行。 DML事件是表或视图上的INSERT,UPDATE或DELETE语句。 触发任何有效事件时触发这些触发器,无论表行是否受到影响。

如果你有一个循环循环,表A有一个影响表B的触发器,而表B有一个影响表A的触发器,你可以使用TRIGGER_NESTLEVEL来管理它,或者检查是否{{3}}在实际执行任何操作之前,1}}或inserted包含任何行。