条件语句中的子查询语句的语法没有检查

lovvver 2009-09-10 10:27:15

create table tb1(id int identity(1,1),name varchar(10),remark varchar(50) default '');
create table tb2(xid int identity(1,1),name varchar(10));

insert into tb1(name)
select 'a'
union all select 'b'
union all select 'c'
insert into tb2(name) select 'x'

select * from tb1 where id in(select id from tb2)
select * from tb1 where id in(select xid from tb2)

drop table tb1
drop table tb2;


结果是:
id name remark
----------- ---------- --------------------------------------------------
1 a
2 b
3 c

(3 row(s) affected)

id name remark
----------- ---------- --------------------------------------------------
1 a


从这段脚本执行后,就可以发现问题:
为何select * from tb1 where id in(select id from tb2)在执行的时候不对条件中的子查询语句做语法检查呢?而且默认的等价于1=1呢?
...全文
224 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
lovvver 2009-09-10
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 chuifengde 的回复:]
sqlserver在分析第一条语句的时候确定tb2中的Id来自tb1,所以两条语句的执行计划都不一样,第一个用到了临时表,第二个是流水线型,如果两表加上索引,第二个比第一个肯定快
[/Quote]

两条语句的执行计划没看出有什么不同哦,只是里面的分析参数稍微有点儿不同
chuifengde 2009-09-10
  • 打赏
  • 举报
回复
sqlserver在分析第一条语句的时候确定tb2中的Id来自tb1,所以两条语句的执行计划都不一样,第一个用到了临时表,第二个是流水线型,如果两表加上索引,第二个比第一个肯定快
LIHY70 2009-09-10
  • 打赏
  • 举报
回复
没遇到过, 学习了~
guguda2008 2009-09-10
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 lovvver 的回复:]
看来大家在写sql语句的时候,还是要小心类似的这些泥坑,我今天早上碰到了这个问题,代码都发布出去了,结果被测出问题来了。
[/Quote]
这个问题的关键就是SELECT ID没有写成SELECT TB2.ID,只要注意书写习惯应该就可以避免了。谢谢LZ分享问题。
lovvver 2009-09-10
  • 打赏
  • 举报
回复
看来大家在写sql语句的时候,还是要小心类似的这些泥坑,我今天早上碰到了这个问题,代码都发布出去了,结果被测出问题来了。
华夏小卒 2009-09-10
  • 打赏
  • 举报
回复
收藏了
fwacky 2009-09-10
  • 打赏
  • 举报
回复
oracl ,也样,我试了!
指间扣 2009-09-10
  • 打赏
  • 举报
回复
没见过…… 学习了……
lovvver 2009-09-10
  • 打赏
  • 举报
回复
回复guguda2008:

“IN好像是就是OR的简写,用OR的话如果有错误就会忽略。 ”
如果IN是OR的简写,何谓简写?都是俩字母,呵呵,关键的是,这从语法上是讲不通的。
fwacky 2009-09-10
  • 打赏
  • 举报
回复
这次,Microsoft 丢人,丢大了!
============================
不知,oracl 有没有这个问题?
guguda2008 2009-09-10
  • 打赏
  • 举报
回复
又测了一下,
select * from tb1 where id in(select id from tb2 where xid=1)
出全部
select * from tb1 where id in(select id from tb2 where xid=2)
没有数

这样可以看出这个SELECT ID中的ID是TB1的ID而不是TB2的ID,当TB2的WHERE有记录时会将TB1的所有结果集返回(因为T2和T1没有关联条件),反之则不会返回结果集。
sdhdy 2009-09-10
  • 打赏
  • 举报
回复
貌似有这个问题。
soft_wsx 2009-09-10
  • 打赏
  • 举报
回复
select * from tb1 a where exists  (select id from tb2 where a.id = id )
EXISTS
lovvver 2009-09-10
  • 打赏
  • 举报
回复
回复guguda2008:

exists也没有检查:

create table tb1(id int identity(1,1),name varchar(10),remark varchar(50) default '');
create table tb2(xid int identity(1,1),name varchar(10));

insert into tb1(name)
select 'a'
union all select 'b'
union all select 'c'
insert into tb2(name) select 'x'

select * from tb1 where exists (select id from tb2)
select * from tb1 where exists (select xid from tb2)

drop table tb1
drop table tb2;


结果:
id name remark
----------- ---------- --------------------------------------------------
1 a
2 b
3 c

(3 row(s) affected)

id name remark
----------- ---------- --------------------------------------------------
1 a
2 b
3 c

(3 row(s) affected)

fwacky 2009-09-10
  • 打赏
  • 举报
回复

select * from tb1 where exists (select id from tb2 where tb1.id = id )
这个也一样,也是错了!
pt1314917 2009-09-10
  • 打赏
  • 举报
回复
之前完美也贴个这样的。结果没找到说法。。。
xupeihuagudulei 2009-09-10
  • 打赏
  • 举报
回复
学习
fwacky 2009-09-10
  • 打赏
  • 举报
回复


select * from tb1 where id not in (select id from tb2)
这个本来是,3条记录,可是一条都没有出!
lovvver 2009-09-10
  • 打赏
  • 举报
回复
如果我在敲sql语句的时候误把select * from tb1 where id in(select xid from tb2)中的select xid敲成select id,那么取出的数据就会有问题(全取出),但是却得不到提示,因为语法检查跳过了。所以,这个在写sql语句的时候,是一个潜在的泥坑啊
大概在网上搜了一下没搜到相关的文章,干脆提到论坛里供大家讨论学习吧。
有没有高手解释一下。
xiequan2 2009-09-10
  • 打赏
  • 举报
回复
学习
加载更多回复(11)

34,593

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧