SQL Server触发器未按预期运行

SQL Server触发器未按预期运行,sql,sql-server,database,triggers,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 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”无效。)

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


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

您在
更新中的错误是因为查询被视为相关子查询:

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

插入中唯一的错误是逻辑错误。id在该上下文中完全有效,因为id是Test_Table1_Tbl中的一列。使用create table和create trigger ddl,我无法创建触发器。可能在创建触发器时,Test_Table2_Tbl中有一个名为id的列?这就解释了为什么你可以使用触发器而不是列。