create table #a(
F1 int ,
F2 int,
F3 int,
F4 int
)
insert into #a
select 1,2,3,4 union all
select 2,2,3,4 union all
select 3,2,3,4 union all
select 4,2,3,4 union all
select 5,2,3,4
create table #b(
F1 int ,
F2 int
)
insert into #b
select 2,1 union all
select 3,1 union all
select 4,1
select * from #a
select * from #b
select * from #a where F1 in (select F3 from #b)
为什么要报错呢?
select F3 from #b 表中并没有F3字段
个人觉得 这里F3是属于一个常数了,取的是a表当前行的F3字段的值,也就是这个查询等价于查找a表F1和F3值相等的行
这样的化,就很难发现代码的错误了
@dunkS: sql server我不太熟,但是这里如果指定表名的话,应该是会报错的。我用Mysql一般做类似查询的时候,我喜欢把外表和内表都起上别名,取字段的时候就是 别名.字段名,这样就会清晰很多,也可以避免上面的问题。
Create table #b(
F1 int,
F2 int,
F3 int
)
你创建表的时候本来就没添加F3字段吧
你再仔细看看,没有F3
@dunkS: 是的,没有,所以会报错吧,select F3 from #b,不是査的#b表里的字段吗
@气氛组(红尘熊): 没报错
@dunkS: 应该是没有从属的事,F3因为#b没有,而你前面也查询了#a,就默认了F3是#a的,并复给了select F3 from #b这次查询的结果,所以就类似select * from #a where F1=F3
你这字段不加属主,应该报错,应该f1和f3都是常量而非字段?
能复现,f1到f4都不错,f5报错了。如果在#a里加了字段f5,那么f5也不报错了
找到答案了
https://learn.microsoft.com/zh-cn/sql/relational-databases/performance/subqueries?view=sql-server-2017#qualifying
如果某个子查询中引用的列不存在于该子查询的 FROM 子句引用的表中,而存在于外部查询的 FROM 子句引用的表中,则该查询可以正确执行。 SQL Server使用外部查询中的表名称隐式限定子查询中的列。
有点迷糊,那这样的话,子查询的返回结果这么得到呢。用了这么多年SQL server,居然不知道还要这个规则......
@会长: 子查询并不能单独执行的,根据sqlserver的规则,在子查询中是把#b隐式用#a替换了
@十一年新: 彩
这里的F3 其实是 #a 表的 F3 所以不会报错的
sql 改成
select * from #a where F1 in (select #b.F3 from #b)
就报错了
这是因为再查询的时候先是查找#b是否有F3字段 如果没有就在a#的表去找 此时再找不到才报错
select * from #a where F1 in (select F3 from #b) 这个查询语句如果#b没有字段F3 这时可以把查询语句理解为
select * from #a where F1 in (F3) 此时#b表是没有任何用处的