After Delete触发器中内连接无结果,子查询有结果的原因?
这问题我碰到过类似的情况,咱们一步步捋清楚:
首先得明确After Delete触发器里deleted表的作用——它存的是触发器所在表里刚被删掉的所有行,这是核心前提。
然后看你的两条查询:
第一条:SELECT TOP 1 t.Id FROM deleted d INNER JOIN Table t ON t.Id = d.Id
第二条:SELECT TOP 1 t.Id FROM Table t WHERE t.Id = (SELECT TOP 1 d.Id FROM deleted d)
你说Table是引用触发器所在表的关联表,那咱们假设触发器在「主表A」,Table是「关联表B」,B本来应该通过外键(比如A_Id)关联A的主键Id,但你第一条查询里用的是t.Id = d.Id——也就是把B的主键Id和A的主键Id直接做匹配。
这时候问题就来了:如果B的主键Id和被删除的A的Id没有对应关系(或者说B里根本没有主键等于这个被删Id的行),INNER JOIN就会因为两边没有匹配的行,返回空结果。
而第二条查询不一样:它先从deleted里揪出被删A的Id,然后直接去B里找主键Id等于这个值的行——只要B里刚好存在这么一行(哪怕这行和A的关联其实是通过别的字段),就会返回结果。
举个具体例子:假设主表A被删的行Id是10,关联表B里有一行Id=10,但它关联的A的Id是20(外键A_Id=20)。这时候第一条查询用B.Id=A.Id关联,B的Id=10对应A的Id是20,和deleted里的A的Id=10对不上,自然没结果;第二条直接查B里Id=10的行,一找一个准,所以有结果。
说白了,第一条查询的关联条件写错了,不符合你实际的表关联逻辑,而第二条刚好是“撞”到了B里有对应Id的行,才出现了结果差异。
内容的提问来源于stack exchange,提问作者Ian Warburton

