暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

有关字段解析顺序的问题

在墨天轮中有这么一道题 https://www.modb.pro/test/20230303,评论中有网友给出了解释,题目中是一条delete语句,为了便于说明理解,这里通过select语句说明。

create table t1 (id NUMBER,name VARCHAR2(10));
create table t2 (id NUMBER);
insert into t1 values(1,‘abcd’);
insert into t2 values(1);
commit;

SQL> SELECT * from t1 where name in (select name from t2); <–t2表中没有name列,本以为会报错,但却能执行成功

    ID NAME

     1 abcd

SQL> SELECT * from t1 where name in (select t1.name from t2);

    ID NAME

     1 abcd

SQL> SELECT * from t1 where name in (select t2.name from t2);
SELECT * from t1 where name in (select t2.name from t2)
*
ERROR at line 1:
ORA-00904: “T2”.“NAME”: invalid identifier

SQL> SELECT * from t1 where name in (select type from t2);
SELECT * from t1 where name in (select type from t2)
*
ERROR at line 1:
ORA-00904: “TYPE”: invalid identifier

SQL> SELECT * from t1 where name in (select t2.type from t2);
SELECT * from t1 where name in (select t2.type from t2)
*
ERROR at line 1:
ORA-00904: “T2”.“TYPE”: invalid identifier

通过以上查询可知子查询()中的name其实是t1.name,即原sql其实是
SELECT * from t1 where name in (select t1.name from t2);
所以若t2表不是空表,有至少一行数据,原sql将返回SELECT * from t1的结果。
若t2表是空表,原sql不会有结果返回。

mos文档 Doc ID 1327574.1 和 Doc ID 124014.1有相关的解释,这不是bug,符合ANSI/ISO SQL standard。但举了一个不太恰当的例子,说原sql可以理解为select t1.* from t1,t2;或 select t1.* from t1,t2 where t1.name=t1.name;但如果t2表的行数大于1行,结果就不一样了,如下所示。

SQL> insert into t2 values(2);

1 row created.

SQL> insert into t2 values(3);

1 row created.

SQL> select * from t1;

    ID NAME

     1 abcd

SQL> select * from t2;

    ID

     1
     2
     3

SQL> SELECT * from t1 where name in (select name from t2);

    ID NAME

     1 abcd

SQL> select t1.* from t1,t2;

    ID NAME

     1 abcd
     1 abcd
     1 abcd

SQL> select t1.* from t1,t2 where t1.name=t1.name;

    ID NAME

     1 abcd
     1 abcd
     1 abcd

SQL>

对于
select t1.id,name,t2.id
from t1,t2
where t1.id=t2.id
知道name其实是t1.name

对于原sql
SELECT * from t1 where name in (select name from t2);
一开始认为是SELECT * from t1 where name in (select t2.name from t2)执行会报错,还是没正确认识啊,实质上就是字段解析顺序的问题,若t2表有name列,会将原sql中的(select name from t2)解析为(select t2.name from t2)。若t2表没有name列但t1表有name列,会将原sql中的(select name from t2)解析为(select t1.name from t2)。

最后修改时间:2023-03-09 16:39:45
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论