触发器未在 SQL Server 中触发

Trigger is not firing in SQL Server

提问人:Jason Orman 提问时间:11/14/2023 最后编辑:Jason Orman 更新时间:11/15/2023 访问量:72

问:

我创建了以下触发器,它应该正在寻找更新。我的理解是,更新会在表和表中创建一个条目。所以我不确定为什么以下内容不起作用。(它正在检查值是否从一个更改为另一个,如果是,请将其记录在第二个表中)。DELETEDINSERTED

CREATE TRIGGER [dbo].[captureNameChainToLocateComplete] 
ON [dbo].[tblLand]
AFTER UPDATE
AS 
BEGIN
    DECLARE @old AS varChar(50)
    DECLARE @new AS varChar(50)
    DECLARE @name AS varchar(50)
    DECLARE @now AS dateTime
    DECLARE @recordId AS varchar(50)

    SELECT @old = d.sSubdivision FROM DELETED d
    SELECT @new = i.sSubdivision FROM INSERTED i

    SELECT @name = (SELECT TOP 1 sHistoryUser 
                    FROM tblDocumentHistory 
                    ORDER BY dtHistoryDate DESC)
    SELECT @recordId = (SELECT TOP 1 iRecordId 
                        FROM tblDocumentHistory 
                        ORDER BY dtHistoryDate DESC)
    SELECT @now = (SELECT GETDATE())

    IF @old = 'NAME CHAIN' AND @new = 'LOCATE COMPLETE'
    BEGIN
        INSERT INTO nameChainLog (recDate, irecordId, userName) 
        VALUES (@now, @recordId, @name)
    END
    ELSE
    BEGIN
        INSERT INTO nameChainLog (recDate, irecordId, userName) 
        VALUES (@now, 'test', 'test')
    END
END

编辑:第二个插入仅用于故障排除,以便在发生其他情况时尝试记录。

SQL Server 触发 sql-update

评论

7赞 Craig 11/14/2023
根据更新的发生方式(例如,更新单行或更新多行),DELETED 和 INSERTED 表很可能包含多行。因此,您不能只将变量的值设置为 DELETED 或 INSERTED 表中的列 - 您的变量可能只会获得最后一行的值(或者,老实说,无论哪一行是 SQL Server 喜欢的)。如果 UPDATE 语句影响多行(它可以影响),则触发器需要相应地处理 DELETED 和 INSERTED 表
5赞 siggemannen 11/14/2023
在触发器中放置一些 PRINT,并测试一些更新以查看会发生什么。仅凭你的帖子是不可能说出了什么问题。正如其他人所说,一旦你在触发器中将东西分配给变量,你就可能走上了失败的道路,你必须使用整个插入/删除的块。另外,代码格式有问题
6赞 Dale K 11/14/2023
您仍然应该始终编写触发器来处理集合,而不是单行,因为没有什么可以阻止您编写影响多行的 SQL 更新语句。
5赞 Squirrel 11/14/2023
沉默的虫子
3赞 Nick.Mc 11/14/2023
在本例中,tblland 表仅更新了一行您需要针对所有情况进行编码。这是一个等待发生的错误。有足够多的意外错误,不要不遗余力地引入已知的错误。这样做的目的是什么?仅打开 SQL Server CDC 或临时表可能更容易。这其中不涉及任何代码。

答:

1赞 Gesuele Russello 11/15/2023 #1

你应该尝试这样的事情,你需要涵盖多个更新

  CREATE TRIGGER [dbo].[captureNameChainToLocateComplete] 
ON [dbo].[tblLand]
AFTER UPDATE
AS 
BEGIN
    DECLARE @old AS varChar(50)
    DECLARE @new AS varChar(50)
    DECLARE @name AS varchar(50)
    DECLARE @now AS dateTime
    DECLARE @recordId AS varchar(50)

    -- Use a cursor to handle multiple rows in DELETED and INSERTED
    DECLARE cursorTrigger CURSOR FOR
    SELECT d.sSubdivision, i.sSubdivision
    FROM DELETED d
    JOIN INSERTED i ON d.irecordId= i.irecordId

    OPEN cursorTrigger
    FETCH NEXT FROM cursorTrigger INTO @old, @new

    WHILE @@FETCH_STATUS = 0
    BEGIN
        SELECT @name = (SELECT TOP 1 sHistoryUser 
                        FROM tblDocumentHistory 
                        ORDER BY dtHistoryDate DESC)
        SELECT @recordId = (SELECT TOP 1 iRecordId 
                            FROM tblDocumentHistory 
                            ORDER BY dtHistoryDate DESC)
        SELECT @now = GETDATE()

        IF @old = 'NAME CHAIN' AND @new = 'LOCATE COMPLETE'
        BEGIN
            INSERT INTO nameChainLog (recDate, irecordId, userName) 
            VALUES (@now, @recordId, @name)
        END
        ELSE
        BEGIN
            INSERT INTO nameChainLog (recDate, irecordId, userName) 
            VALUES (@now, 'test', 'test')
        END

        FETCH NEXT FROM cursorTrigger INTO @old, @new
    END

    CLOSE cursorTrigger
    DEALLOCATE cursorTrigger
END