Sql 使用联接时,查询抛出ORA-00904无效标识符
我遇到了一些奇怪的行为,这些行为阻止了我以我喜欢的方式设置查询。如果您有任何想法,我将不胜感激。如果有任何关于表格的信息对我有帮助,请告诉我。我仔细看了看,没有任何东西向我扑来,这可能会导致这种情况,但我也不知道我在寻找什么。这就是行为 这很好:Sql 使用联接时,查询抛出ORA-00904无效标识符,sql,oracle,Sql,Oracle,我遇到了一些奇怪的行为,这些行为阻止了我以我喜欢的方式设置查询。如果您有任何想法,我将不胜感激。如果有任何关于表格的信息对我有帮助,请告诉我。我仔细看了看,没有任何东西向我扑来,这可能会导致这种情况,但我也不知道我在寻找什么。这就是行为 这很好: Select * From SCHEMA_A.TABLE_A a, SCHEMA_B.TABLE_B b, SCHEMA_C.TABLE_C c, SCHEMA_A.TABLE_D d Where b.fr
Select *
From
SCHEMA_A.TABLE_A a,
SCHEMA_B.TABLE_B b,
SCHEMA_C.TABLE_C c,
SCHEMA_A.TABLE_D d
Where
b.friend_id = c.friend_id
AND a.group_id = d.group_id
AND b.group_cd = d.group_cd
但这将返回ORA-00904:b.friend\u id=c.friend\u id:无效标识符
Select *
From
SCHEMA_A.TABLE_A a,
SCHEMA_B.TABLE_B b,
SCHEMA_A.TABLE_D d
Join
SCHEMA_C.TABLE_C c
On
b.friend_id = c.friend_id
Where
a.group_id = d.group_id
AND b.group_cd = d.group_cd
Select *
From
SCHEMA_A.TABLE_A a,
SCHEMA_B.TABLE_B b
Join
SCHEMA_C.TABLE_C c
On
b.friend_id = c.friend_id
Join
SCHEMA_A.TABLE_D d
On
a.group_id = d.group_id
AND b.group_cd = d.group_cd
这将返回ORA-00904:b.group\U cd=d.group\U cd:无效标识符
Select *
From
SCHEMA_A.TABLE_A a,
SCHEMA_B.TABLE_B b,
SCHEMA_A.TABLE_D d
Join
SCHEMA_C.TABLE_C c
On
b.friend_id = c.friend_id
Where
a.group_id = d.group_id
AND b.group_cd = d.group_cd
Select *
From
SCHEMA_A.TABLE_A a,
SCHEMA_B.TABLE_B b
Join
SCHEMA_C.TABLE_C c
On
b.friend_id = c.friend_id
Join
SCHEMA_A.TABLE_D d
On
a.group_id = d.group_id
AND b.group_cd = d.group_cd
这同样有效:
Select *
From
SCHEMA_A.TABLE_A a,
SCHEMA_B.TABLE_B b
Join
SCHEMA_C.TABLE_C c
On
b.friend_id = c.friend_id
Join
SCHEMA_A.TABLE_D d
On
b.group_cd = d.group_cd
Where
a.group_id = d.group_id
尝试使用
关键字,该关键字是为同一列名上的join
而设计的
Select *
From
SCHEMA_A.TABLE_A a,
SCHEMA_B.TABLE_B b
Join
SCHEMA_C.TABLE_C USING(friend_id)
Join
SCHEMA_A.TABLE_D d using(group_id)
where b.group_cd = d.group_cd;
另外,请确保使用正确的用户执行其他查询,因为没有正确权限的用户将抛出无效标识符
编辑:实际问题是您正在将表C
与表D
连接,但连接条件引用了表B
将其更改为
Select *
From
SCHEMA_A.TABLE_A a,
SCHEMA_A.TABLE_D d,
SCHEMA_B.TABLE_B b
Join
SCHEMA_C.TABLE_C c using(friend_id)
Where
a.group_id = d.group_id
AND b.group_cd = d.group_cd;
对其他查询应用相同的逻辑,在执行联接时,您不会联接到一组表,而是联接到from
子句中提到的最后一个表,因此它无法访问表B
对于可能有无效标识符错误的其他人,请确保您的数据库不区分大小写,否则请确保使用正确的大小写。我相信您已经遇到了SQL中处理连接作用域/优先级的复杂性。由于我自己不是一名数据库程序员,我无法真正告诉您为什么它会这样工作,但我确实看到了查询解析器行为的一些逻辑
在第一个查询中,所有连接都是交叉连接。因此,它们应该具有相同的优先级。因此,在计算联接时,所有联接列都是已知的
在第二个查询中,您有交叉联接和内部联接的组合。如果我们假设内部联接优先于交叉联接,那么在将任何其他表添加到混合中之前,表c和d将被联接。因此,当您在内部联接中引用b.friend\u id
时,查询解析器无法使用该列来计算联接
在第三个查询中,表b、c和d之间的内部联接优先于交叉联接。因此,列a.group\u id
在计算内部联接条件时不可用。在最终查询中将表a从内部联接条件中取出时,查询不再具有冲突的优先级。这里的问题是联接类型的混合。当您在FROM
子句中使用逗号分隔的表格时,每个术语都会单独计算。以以下为例:
From
SCHEMA_A.TABLE_A a,
SCHEMA_B.TABLE_B b,
SCHEMA_A.TABLE_D d
Join
SCHEMA_C.TABLE_C c
On
b.friend_id = c.friend_id
数据库正在尝试解析b.friend\u id=C.friend\u id
上的架构A.TABLE\D加入架构C.TABLE\C。在此范围内,b
没有任何意义(它是一个单独的术语)
对于您的第三个版本,我得到了“A”。“GROUP\u ID”:无效标识符,这也符合此解释
最后,您应该从中吸取的教训是不要混合联接类型。他已经有了成功运行的代码。他正在寻找不一致行为的解释。另一种可能是区分大小写,但您的两个查询都是以相同的方式编写的。完全是这样。我没有意识到这样的工作,但它现在有了完美的意义。非常感谢!仅供参考,我认为使用的问题是,它应该更换,而不是跟进it@philfo是的,如果使用
关键字,则在
上不能有我的错误,我将进行编辑。这就是为什么您不应该将旧的Oracle类型联接与正确的ANSI类型联接混合使用,因为联接顺序和范围变得更加不清晰。。。坚持其中之一,最好是ANSI*8-)它们不是真正的交叉连接;使用旧的逗号分隔表语法,Oracle使用where
条件作为联接条件。(事实上,它仍然可以与ANSI连接,但这是另一个故事)。但你仍然是对的,C和D首先连接,B不在范围内。实际上,逗号分隔的表列表是一个隐含的交叉连接。看见这就是为什么出于可读性和性能原因不鼓励这种做法。在同一页中:“交叉连接的结果可以通过使用WHERE子句进行过滤,该子句可能会产生与内部连接等效的结果。”我同意这是一种没有WHERE
的交叉连接,但是,因为有一个内部连接,所以它是一个内部连接-虽然当您使用ANSI术语来表示Oracle的语法(甚至*8-)时,这个术语会有点尴尬,但我在很大程度上是在吹毛求疵。您是对的,返回的结果将与内部连接相同,但是查询解析器获得该结果的方式可能会大不相同。如果您正在处理一个非常大的数据集,必须加载所有记录,对所有记录应用交叉连接,那么过滤器将在内存中生成一个巨大的数据集。希望查询解析器能够将交叉连接优化为内部连接。如果是这样,那么你说它们是等价的是绝对正确的。除非有这样的保证,否则我不会说与WHERE
的交叉连接与内部连接相同。@bluecollarcoder:在应用WHERE
条件之前,它在逻辑上是交叉连接,但数据库不会这样计算。如果您查看OP中查询的解释计划,则不会看到笛卡尔积。很长一段时间以来,数据库一直在评估where
子句中的联接,并在优化查询时将其考虑在内。