我有一个像
这样的查询SELECT tran_number
FROM table_a WHERE customer_id IN
(SELECT customer_id
FROM table_b
WHERE customer_key = 89564
AND ( other_phn_area_code
|| other_phnum_pfx_num
|| other_phnum_sfx_num IN
(123456789)))
AND phn_area_code || phnum_pfx_num || phnum_sfx_num IN (123456789)
上面的代码工作正常。关注的是内部查询(下面单独复制内部查询)...
(SELECT customer_id
FROM table_b
WHERE customer_key = 89564
AND ( other_phn_area_code
|| other_phnum_pfx_num
|| other_phnum_sfx_num IN
(123456789)))
当我执行此查询时,我收到的错误为customer_id: invalid identifier
。实际上,table_b
没有任何名为customer_id
的字段。如果是这样,那么当我将它用作上面的内部查询时,它是如何工作的,没有任何问题。
请帮助我理解这一点。
以下数据库详情
Oracle 11G Enterprise edition 11.2.0.2.0
PL/SQL Release 11.2.0.2.0
答案 0 :(得分:7)
如果该内部选择的where
条件具有结果,则将选择customer_id
中的table_a
列。
如果没有,则不会被选中。外部选择检查具有in
条件的那个。这就像说:“只有在内部选择返回true时才返回一些东西。”
答案 1 :(得分:3)
这是范围的问题。 Oracle验证从最里面的子查询开始并向外工作的标识符。如果我们在原始查询中添加表别名,事情可能会变得更加清晰:
SELECT t1.tran_number
FROM table_a t1
WHERE t1.customer_id IN
(SELECT t1.customer_id
FROM table_b t2
WHERE t2.customer_key = 89564
AND ( t2.other_phn_area_code
|| t2.other_phnum_pfx_num
|| t2.other_phnum_sfx_num IN
(123456789)))
AND t1.phn_area_code || t1.phnum_pfx_num || t1.phnum_sfx_num IN (123456789)
实际上,外部查询使用子查询作为EXISTS的测试,即仅检查是否存在给定值的CUSTOMER_KEY和其他列。如果这不是您想要的,那么您应该更改子查询中的列名称。 (这是一个相当不错的选择:你可能从主查询得到令人费解的结果,这就是为什么你要孤立地调查子查询)。
在这些场景中使用别名总是很好的做法。如果你给子查询别名如下:
....
WHERE t1.customer_id IN
(SELECT t2.customer_id
FROM table_b t2
WHERE t2.customer_key = 89564
....
错误很明显。
SQL Reference确实解释了子查询中作用域的操作,但很难找到。 it says是什么:
“Oracle通过查看来解析子查询中的不合格列 在子查询中命名的表,然后在表中命名的表中 父声明“
您可以在PL / SQL文档中找到更明确的范围解释; SQL子查询以相同的方式工作。 Find out more
答案 2 :(得分:0)
这是IN的一个已知错误。如果使用表别名,则会出现错误
SELECT tran_number
FROM table_a WHERE customer_id IN
(SELECT b.customer_id
FROM table_b b
WHERE customer_key = 89564
AND ( other_phn_area_code
|| other_phnum_pfx_num
|| other_phnum_sfx_num IN
(123456789)))
AND phn_area_code || phnum_pfx_num || phnum_sfx_num IN (123456789)
还使用EXISTS来避免这种类型的静默行为
SELECT tran_number
FROM table_a as t1 WHERE EXISTS
(SELECT *
FROM table_b as b
WHERE customer_key = 89564
AND ( other_phn_area_code
|| other_phnum_pfx_num
|| other_phnum_sfx_num IN
(123456789))
AND b.customer_id =t1.customer_id)
AND phn_area_code || phnum_pfx_num || phnum_sfx_num IN (123456789)