使用T-Sql IN运算符时要小心

时间:2017-04-07 10:14:51

标签: sql-server tsql

有没有人解释为什么这种查询因为IN运算符而在id_t1 = id_t1中运行?

我的同事删除了整个表行,即使他想删除一些行,当我们分析查询时,我们意识到使用" IN"运营商。查询结构不合适,但它运行。 我想展示一下如何成为:

create table #table1(id_t1 int)
create table #table2(id_t2 int)

--insert data
insert into #table1(id_t1) values(1)
insert into #table1(id_t1) values(2)
insert into #table1(id_t1) values(3)
insert into #table1(id_t1) values(4)

insert into #table2(id_t2) values(10)
insert into #table2(id_t2) values(20)
insert into #table2(id_t2) values(30)
insert into #table2(id_t2) values(40)

您可以看到#table2 中没有 id_t1 , 当你运行

select id_t1 from #table2  where id_t2 = 10 

查询返回:

Invalid column name 'id_t1'.

但它可以与"一起使用"操作

select * from #table1 where id_t1 in (select id_t1 from #table2  where id_t2 = 10)

它返回整个#table1

id_t1
---------
1
2
3
4

用于删除操作时,如上所述

delete from #table1 where id_t1 in (select id_t1 from #table2  where id_t2 = 10)

您的#table1没有更多行:)

select * from #table1


id_t1
-----------

(0 row(s)


drop table #table1
drop table #table2

我的整个示例脚本可轻松复制/粘贴:

create table #table1(id_t1 int)
create table #table2(id_t2 int)

--insert data
insert into #table1(id_t1) values(1)
insert into #table1(id_t1) values(2)
insert into #table1(id_t1) values(3)
insert into #table1(id_t1) values(4)

insert into #table2(id_t2) values(10)
insert into #table2(id_t2) values(20)
insert into #table2(id_t2) values(30)
insert into #table2(id_t2) values(40)

select * from #table1 where id_t1 in (select id_t1 from #table2  where id_t2 = 10)


delete from #table1 where id_t1 in (select id_t1 from #table2  where id_t2 = 10)


select * from #table1

drop table #table1
drop table #table2

3 个答案:

答案 0 :(得分:4)

在您的选择查询中

select * from #table1 where id_t1 in (select id_t1 from #table2  where id_t2 = 10)

SQL将其解释为

select * from #table1 where #table1.id_t1 in (select #table1.id_t1 from #table2  where id_t2 = 10)

因此,对于#table1中的每一行,in子句是#table1.id_t1的值,对表2的每一行重复。当然,每行都符合条件。

这就是为什么你不应该先运行删除语句而不先检查select ...

答案 1 :(得分:3)

这是因为id_t1确实存在于table1和你没有说id_t1必须来自正确表格的地方。
为每个表使用别名可以很容易地解决这个问题。

这样会更好

select * 
from   #table1 t1 
where  t1.id_t1 in (select t2.id_t1 from #table2 t2 where t2.id_t2 = 10)

现在你得到Invalid column name id_t1就像预期的那样

答案 2 :(得分:0)

子查询

select id_t1 from #table2  where id_t2 = 10

将返回Id_t1对应的#Table1列,因此条件IN始终匹配。

正确的查询应该是

select * 
from #table1 where id_t1 in 
                          (select t2.id_t2 from #table2 t2  where t2.id_t2 = 10)

或使用EXIST

select * from #table1 t1 
where Exist (select t2.id_t2 from #table2 t2  where t2.id_t2 = 10 and t2.id_t2 = t1.id_t1)

或使用INNER JOIN

select * 
from #table1 t1
inner join #table2 t2 on t1.id_t1 = t2.id_t2
where t2.id_t2 = 10

删除时逻辑相同