为何子查询看似引用不存在字段的SQL语句是合法的?
这条SQL合法的核心原因及对应SQL语法原则
这是SQL标准中标识符作用域查找规则和相关子查询的特性决定的,完全符合通用SQL规范。
1. 标识符逐层查找规则
SQL解析字段引用时的默认查找顺序是:
- 优先在当前子查询的所有可用数据源(FROM后的表/子查询结果)中搜索匹配的字段名
- 如果当前层找不到,就向上一层父查询的作用域搜索,逐层向外直到最外层查询
- 所有层都找不到匹配字段才会抛出语法错误
你给出的示例中:
- 最内层子查询
x的结果仅包含astring字段,无法匹配abool - 数据库自动向外查找,找到外层
table1的abool字段,直接引用生效
2. 子查询的执行逻辑
你示例中WHERE后的是标量子查询(要求返回单行单列结果),内层子查询select astring from table2 limit 1固定返回1行,所以整个子查询的返回值就是外层table1当前行的abool字段值,执行等价于:
select * from table1 where abool;
自然可以正常执行。
3. 实际开发注意事项
这种隐式的外层字段引用非常容易产生不易排查的逻辑错误,因此业内通用开发规范要求:
- 所有查询的表都指定别名
- 字段引用必须带上所属表的别名前缀
如果你的示例中子查询的abool加上子查询别名x,写成select x.abool from (...) x,就会直接抛出字段不存在的错误,符合你最初的直觉判断。
内容的提问来源于stack exchange,提问作者Manolo
相关产品推荐
相关产品推荐

