以下查询不起作用。由于temp.col
引用了在该上下文中不可用的内容,因此预计会失败。
with temp as (
select 'A' col from dual
union all
select 'B' col from dual
)
select *
from temp,
(select level || temp.col from dual connect by level < 3);
来自Oracle的错误消息是:ORA-00904:“TEMP”。“COL”:标识符无效
但为什么下一个查询有效呢?我将CAST / MULTISET视为从SQL表转换为集合类型的一种方式,而TABLE则返回到SQL表。为什么我们使用这种往返旅行?我想让查询工作,但是怎么做?
with temp as (
select 'A' col from dual
union all
select 'B' col from dual
)
select *
from temp,
table(
cast(
multiset(
select level || temp.col from dual connect by level < 3
) as sys.odcivarchar2list
)
) t;
结果是:
COL COLUMN_VALUE
--- ------------
A 1A
A 2A
B 1B
B 2B
查看第二列的名称COLUMN_VALUE
。看起来像构造CAST / MULTISET或TABLE之一生成的名称。
修改
通过下面接受的答案,我检查了文档,发现TABLE机制是一个表集合表达式。圆括号之间的表达式是集合表达式。文档定义了一种称为左相关的机制:
collection_expression可以引用定义到的表的列 它在FROM子句中的左边。这称为左相关。剩下 只能在table_collection_expression中发生相关。其他 子查询不能包含对外部定义的列的引用 子查询。
所以这就像12c中的LATERAL。
答案 0 :(得分:2)
Oracle允许lateral内联视图引用内联视图中的其他表。
在旧版本中,此功能主要用于优化,如Oracle优化器博客here中所述。在12c中添加明确的侧向连接。您的第一个查询只需要在12c中进行一些小改动:
with temp as (
select 'A' col from dual
union all
select 'B' col from dual
)
select *
from temp,
lateral(select level || temp.col from dual connect by level < 3);
显然,Oracle也默默地使用横向连接进行收集取消。在某些情况下,SQL使用逻辑交叉连接,但这些表明显密切相关;例如XMLTable,JSON_table和查询就像你的第二个例子。在这些情况下,将两个表一起执行是有意义的。我假设在那里使用了横向机制,尽管执行计划和10053优化器跟踪都没有使用单词&#34; lateral&#34;。文档甚至在Collection Unnesting: Examples中有一个与您的非常相似的示例。然而,这个&#34;功能&#34;仍然没有很好的记录。
另一方面,您应该避免使用增加上下文的SQL功能。横向连接,公用表表达式和相关子查询等功能可能很有用,但它们也会使SQL语句更难理解。常规内联视图可以单独运行和理解,并且具有非常简单的界面 - 其投影列。这种简单性使得将小组件组装成大型语句变得更容易。
我建议你重新编写你的查询,如下所示。像处理函数或过程一样处理每个内联视图 - 为它们提供好的名称和注释。当你将它们组装成大而实际的陈述时,它会帮助你。
select col, the_level||col
from
(
--Good comment 1.
select 'A' col from dual union all
select 'B' col from dual
) good_name_1
cross join
(
--Good comment 2.
select level the_level
from dual
connect by level < 3
) good_name_2