【问题标题】:SQL Server trigger not acting as expectedSQL Server 触发器未按预期运行
【发布时间】:2018-10-07 09:42:27
【问题描述】:

我有这两张表:

CREATE TABLE [dbo].[Test_Table1]
(
    [id] [int] IDENTITY(1,1) NOT NULL,
    [f_id] [int] NULL
) ON [PRIMARY]

CREATE TABLE [dbo].[Test_Table2_Tbl]
(
    [f_id] [int] IDENTITY(1,1) NOT NULL,
    [text] [varchar](500) NULL
) ON [PRIMARY]

还有一个触发器:

CREATE TRIGGER [dbo].[trg_Test_Trigger_Delete]
ON [dbo].[Test_Table2_Tbl] 
AFTER DELETE
AS
    INSERT INTO Test_Table2_Tbl (text)
        (SELECT id FROM deleted)

    UPDATE Test_Table1_Tbl
    SET f_id = NULL
    WHERE f_id IN (SELECT id FROM deleted)
GO

敏锐的观察者会意识到“已删除”中不存在“id”。

SQL 在 INSERT 中捕获该错误,但如果没有 INSERT,它会让您添加触发器而不会产生任何抱怨。

为什么它没有捕捉到那个错误? (列名“id”无效。)

我的第二个问题是,为什么在deleted中找不到id时UPDATE语句将EVERY列更新为NULL

我只是非常困惑,需要弄清楚为什么每条记录都与 WHERE 子句匹配。

【问题讨论】:

  • 插入中的唯一错误是逻辑错误。 id 在该上下文中完全有效,因为 id 是 Test_Table1_Tbl 中的一列。
  • 使用您的创建表和创建触发器 ddl 我无法创建触发器。也许您在创建触发器时在 Test_Table2_Tbl 中有一个名为 id 的列?这将解释您如何拥有触发器而不是列。

标签: sql sql-server database triggers


【解决方案1】:

UPDATE 中的错误是因为该查询被视为相关子查询:

UPDATE Test_Table1_Tbl
    SET f_id = NULL
    WHERE Test_Table1_Tbl.f_id IN (SELECT Test_Table1_Tbl.id FROM deleted d);

id 无法在 deleted 中解析,因此 SQL 会寻找下一个级别。

这些是子查询的范围规则。这就是为什么当您有子查询时应该始终使用限定的表名:

UPDATE Test_Table1_Tbl
    SET f_id = NULL
    WHERE Test_Table1_Tbl.f_id IN (SELECT d.id FROM deleted d);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多