一尘不染

左联接中的歧义(仅适用于Oracle?)

sql

我的老板在我创建的查询中发现了一个错误,尽管查询结果证明他是正确的,但我不理解该错误的原因。这是修复之前的查询(简化版):

select PTNO,PTNM,CATCD
from PARTS 
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD);

这是修复后:

select PTNO,PTNM,PARTS.CATCD
from PARTS 
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD);

错误是,显示了CATCD列的空值,即查询结果包括表CATEGORIES的结果而不是PARTS的结果。这是我不明白的:如果原始查询中存在歧义,为什么Oracle不会抛出错误?据我了解,在左联接的情况下,查询(PARTS)中的“主”表具有歧义性。我是错了,还是只是没有正确考虑这个问题?

更新:

这是一个修改后的示例,其中不会引发歧义错误:

CREATE TABLE PARTS (PTNO NUMBER, CATCD NUMBER, SECCD NUMBER);

CREATE TABLE CATEGORIES(CATCD NUMBER);

CREATE TABLE SECTIONS(SECCD NUMBER, CATCD NUMBER);


select PTNO,CATCD 
from PARTS 
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD) 
left join SECTIONS on (SECTIONS.SECCD=PARTS.SECCD) ;

有人知道吗?


阅读 115

收藏
2021-05-30

共1个答案

一尘不染

恐怕我不能告诉你为什么你没有例外,但是我可以推测为什么它选择了CATEGORIES版本的列而不是PARTS版本的列。

据我了解,在左联接的情况下,查询(PARTS)中的“主”表具有歧义性

尚不清楚从概念上看查询时,“主”是指左联接中的左表,还是“驱动”表。但是无论哪种情况,您在“主”表中所看到的都是“主”表。您编写的查询不一定是该查询实际执行中的“主”表。

我的猜测是,Oracle在执行查询时只是使用它命中的第一个表中的列。并且由于SQL中的大多数单独操作不需要先击打一个表,因此DBMS将在解析时决定哪个是最有效的扫描对象。尝试获取查询的执行计划。我怀疑它可能显示它先击中类别,然后击中PARTS。

2021-05-30