SQL Server触发器未按预期执行

时间:2018-04-26 15:50:41

标签: sql sql-server database triggers

我有这两个表:

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'无效。)

我的第二个问题是,为什么在删除时未找到ID时,UPDATE语句会将EVERY列更新为NULL

我很困惑,需要清楚地说明为什么每条记录都匹配WHERE条款。

1 个答案:

答案 0 :(得分:2)

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);