5

我有一段 SQL(你会认为)不会编译,而是从目标表中删除所有行。

考虑这个设置:

create table TableA (ColumnA varchar(200));
create table TableB (ColumnB varchar(200));

insert TableA values ('A'),('B'),('C');
insert TableB values ('A');

然后是下面的sql:

--Returns all rows from TableA
select * from TableA;

--Does not error (ColumnA does not exist on TableB)
delete TableA where ColumnA in (select ColumnA from TableB)

--No Rows are returned
select * from TableA;

上面的 delete 语句会导致从 中删除所有行TableA,而不是在ColumnA中不存在的错误TableB

这里有一个 SQL Fiddle 证明了这一点:http ://www.sqlfiddle.com/#!3/9d883/6

似乎正在接收ColumnA来自,但预计它会“超出范围”。TableA

为什么是这样?

4

2 回答 2

4

由于内部查询中的 ColumnA 与外部查询之间的相关性,这可以按预期工作。

这种常用的相关查询模式是有效的

DELETE TableA WHERE NOT EXISTS (select * from TableB where TableB.ID=TableA.ID)

它会删除在 TableB 中没有相关记录的 TableA 条目。

它表明您可以在相关查询中引用 TableA 列。在您的查询中

delete TableA where ColumnA in (select ColumnA from TableB)

内部查询正在产生

  • TableB 中的每条记录一行
  • 每行一列,其值为来自外部查询的 ColumnA

所以 DELETE 通过

于 2012-10-11T17:36:26.877 回答
3

虽然我理解这种困惑,但它的行为应该如此。ColumnA 仍在“范围内”。事实上,如果你愿意,你可以在你的子查询中加入它。括号不限制范围,但从可读性的角度来看,我可以看到它造成的混乱。

这是另一个示例,说明为什么总是在列名前加上表名(或别名)是个好主意。

于 2012-10-11T17:39:29.427 回答