如何解决为什么我可以交叉加入XMLTABLE?为什么我不必交叉申请?
我看到了一些使用XMLTABLE对Oracle中的逗号分隔的字符串进行排序的示例。尽管我们永远不必通过适当的数据库设计来做到这一点,但它使我感到好奇,并且我完全不了解一件事:
为什么允许交叉连接来自另一个表的XMLTABLE引用列?我希望必须应用横向联接(CROSS APPLY
),但这似乎不是必需的。此查询有效:
select *
from
(
select 'b,a,d' as csv from dual
union all
select 'w,o,r,s,e' as csv from dual
) t
cross join xmltable
(
'if (contains($csv,",")) then string-join(for $str in ora:tokenize($csv,") order by $str return $str,") else $csv'
passing t.csv as "csv"
columns sorted varchar2(4000) path '.'
) x
结果:
+-----------+-----------+ | CSV | SORTED | +-----------+-----------+ | b,d | a,b,d | | w,e | e,w | +-----------+-----------+
我正在传递t.csv
,我认为交叉连接右侧不应该访问该信息。
有人可以解释这里发生了什么吗?我开始认为Oracle出于某种原因弄混了它,从而违反了sql标准。我说的对吗?
如果您可以在这里解释Oracle的功能,那肯定也可以解释为什么添加此功能
where sorted <> 'x'
导致意外结果。出乎我意料的是:-)
带有WHERE
子句的结果:
+-----------+--------+ | CSV | SORTED | +-----------+--------+ | b,d | | w,e | a,d | +-----------+--------+
演示:https://dbfiddle.uk/?rdbms=oracle_18&fiddle=a9497bec423a3facbd29b49b3a40a350
解决方法
您的“为什么”问题可能很难回答;可能是因为这是Oracle使用旧的逗号联接语法然后在以后添加ANSI语法,然后在Oracle 12c中添加CROSS APPLY
来执行相关查询的方法,但是要找到文档来支持这一点将是一个挑战。
但是,如果您可以在应用CROSS JOIN
过滤器子句之前强制对相关的ROWNUM
进行评估(通过执行无用的特定于行的操作,例如生成WHERE
伪列),那么您就可以使用该查询了:
WITH t ( csv ) AS (
select 'b,a,d' from dual union all
select 'w,o,r,s,e' from dual union all
select 'w,e,r' from dual
)
SELECT csv,sorted
FROM (
select ROWNUM as id,t.csv,s.sorted
from t
CROSS JOIN xmltable (
'if (contains($csv,",")) then string-join(for $str in ora:tokenize($csv,") order by $str return $str,") else $csv'
passing t.csv as "csv"
columns sorted varchar2(4000) path '.'
) s
)
WHERE sorted <> 'x';
输出:
CSV | SORTED :---------- | :---------- b,d | a,b,d w,e | e,w w,r | e,w
db 提琴here
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。