微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么我可以交叉加入XMLTABLE?为什么我不必交叉申请?

如何解决为什么我可以交叉加入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 举报,一经查实,本站将立刻删除。