我的老板在我创建的查询中发现了一个错误,尽管查询结果证明他是正确的,但我不理解该错误的原因。这是修复之前的查询(简化版):
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) ;
有人知道吗?
恐怕我不能告诉你为什么你没有例外,但是我可以推测为什么它选择了CATEGORIES版本的列而不是PARTS版本的列。
据我了解,在左联接的情况下,查询(PARTS)中的“主”表具有歧义性
尚不清楚从概念上看查询时,“主”是指左联接中的左表,还是“驱动”表。但是无论哪种情况,您在“主”表中所看到的都是“主”表。您编写的查询不一定是该查询实际执行中的“主”表。
我的猜测是,Oracle在执行查询时只是使用它命中的第一个表中的列。并且由于SQL中的大多数单独操作不需要先击打一个表,因此DBMS将在解析时决定哪个是最有效的扫描对象。尝试获取查询的执行计划。我怀疑它可能显示它先击中类别,然后击中PARTS。