NATURAL JOIN 是一种 JOIN 操作,它根据要连接的两个表中的公共列为您创建隐式连接子句。NATURAL JOIN 可以是 INNER 连接、LEFT OUTER 连接或 RIGHT OUTER 连接。默认为内部联接。来源
因此,如果两个表都有一个公共列,自然连接可以是实现内部连接的一种简写方式。
考虑下表:
SELECT * FROM t1;
/*
ID PLANET
---------- --------
1 jupiter
2 earth
*/
Run Code Online (Sandbox Code Playgroud)
我们将表加入到自身中:
SELECT first.id, first.planet FROM t1 first INNER JOIN t1 second ON first.id=second.id;
/*
ID PLANET
---------- --------
1 jupiter
2 earth
*/
Run Code Online (Sandbox Code Playgroud)
尝试使用自然连接符号做同样的事情:
SELECT id, planet FROM t1 NATURAL JOIN t1;
/*
ID PLANET
---------- --------
1 jupiter
1 jupiter
2 earth
2 earth
*/
Run Code Online (Sandbox Code Playgroud)
鉴于这里的自然连接是使用内部连接实现的,为什么会有多行?
更新:
使用表别名运行相同的连接有不同的输出:
SELECT id, planet FROM t1 first NATURAL JOIN t1 second;
/*
ID PLANET
---------- --------
1 jupiter
2 earth
*/
Run Code Online (Sandbox Code Playgroud)
Oracle 数据库在内部不理解 ANSI 连接语法(除了FULL OUTER JOIN),它将此类查询重写为它自己的旧连接语法。如果启用优化器跟踪,例如:
alter session set events '10053 trace name context forever, level 1';
Run Code Online (Sandbox Code Playgroud)
并运行查询,在生成的跟踪文件中,您可以查看执行的查询的最终形式。
select id, planet from t1 ta natural join t1 tb
Run Code Online (Sandbox Code Playgroud)
转换为(BP 是我的架构):
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT "TB"."ID" "ID","TB"."PLANET" "PLANET" FROM "BP"."T1" "TA","BP"."T1" "TB"
WHERE "TA"."PLANET"="TB"."PLANET" AND "TA"."ID"="TB"."ID"
Run Code Online (Sandbox Code Playgroud)
和
select id, planet from t1 natural join t1
Run Code Online (Sandbox Code Playgroud)
转化为:
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT "T1"."ID" "ID","T1"."PLANET" "PLANET" FROM "BP"."T1" "T1","BP"."T1" "T1"
WHERE "T1"."PLANET"="T1"."PLANET" AND "T1"."ID"="T1"."ID"
Run Code Online (Sandbox Code Playgroud)
这就是问题所在,"T1"."PLANET"="T1"."PLANET" AND "T1"."ID"="T1"."ID"。
但不要问我为什么,这只是 Oracle 中那些“无法解释”的事情之一。
我见过一个案例,其中转换导致类似的模棱两可的最终查询,并且跟踪文件中有实际的错误消息,但数据库仍然返回错误的结果并且没有错误给客户端。
| 归档时间: |
|
| 查看次数: |
979 次 |
| 最近记录: |