【问题标题】:AFTER DELETE, UPDATE trigger not working correctly in SQL删除后,UPDATE 触发器在 SQL 中无法正常工作
【发布时间】:2020-05-08 19:22:24
【问题描述】:

我的一个触发器发生了一些奇怪的事情。我已经构建了一个触发器,它将检查用户是否正在尝试UPDATEDELETE 表中具有[Released_Flag] = 'Y' 的行,如果是这种情况则回滚事务。但是,如果用户尝试将 Released_Flag 字段从“N”更新为“Y”,它仍然会返回错误。

我的触发器是:

CREATE TRIGGER [dbo].[Prevent_Delete] ON  [dbo].[Data_Test]
AFTER DELETE, UPDATE
AS 
BEGIN
SET NOCOUNT ON

    DECLARE @Release_Flag char(1)
    SELECT @Release_Flag = [Release_Flag] FROM deleted

    IF @Release_Flag='Y'
    BEGIN
        RAISERROR('Cannot update or delete a RELEASED variable.',16,1)
        ROLLBACK
    END


END

以上导致UPDATE 语句中的一些问题。它有时会引发错误,即使正在更新的行具有 Release_Flag = 'N'。知道为什么会发生这种情况吗?

我还在触发器中使用了SELECT * FROM [deleted] 来查看发生了什么,尽管[deleted] 表中的某些行显示 Release_Flag = 'Y',尽管它们实际上是 'N'。

【问题讨论】:

  • 应该是BEFORE DELETE
  • 您是否还需要处理多次删除?如果一次删除多个记录会怎样?这段代码会出错
  • 您正在将一个变量设置为 Released_flag 的值,但正如您所说,当您从已删除的表中选择时,您会得到多行。因此,该变量的值可以来自已删除表中的任何行。触发器在整个过程中触发,而不仅仅是一行。此触发器仅适用于个别更新或删除。
  • 您的代码存在一个非常常见的缺陷——您假设只有一行受到更新/删除/合并语句的影响(并且存在于虚拟插入表中)。修复它 - 在互联网上搜索有关如何做到这一点的讨论。这可能会解决您遇到的问题,但没有很难知道的MVCE
  • 以后,我还建议您使用 SET 语句来分配标量值,如果这是您在使用查询时的期望。如果违反该假设,它将生成语法错误,提醒您(或使用您的应用程序的人)发生了严重错误。当您使用 select 语句进行赋值时,其中一行将用于赋值,但您无法保证是哪一行。您可能认为存在基于简单测试的模式,但不能保证。

标签: sql-server tsql database-trigger


【解决方案1】:

我没有意识到的问题是我在表上有另一个触发器来更新表。所以旧触发器触发了这个新触发器,这是我没有考虑到的。

我现在已将这个新触发器的 AFTER UPDATE 部分移动到我的旧触发器中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-04
    • 1970-01-01
    • 2012-02-25
    • 2015-12-02
    • 2020-03-20
    • 2011-06-14
    • 1970-01-01
    • 2017-03-09
    相关资源
    最近更新 更多