问题描述
我具有如下结构的XML类型值
<row id=“124”>
<c1>Name</c1>
<c2>Name2</c2>
</row>
这些列不是固定的,每条记录都会有所不同。
解决方法
您可以使用通配符和位置来获取每个节点中的任何值,并提供尽可能多的columns
子句,使其在一行下具有节点,并且每个子句都定义为具有最大长度的字符串可以从任何一列中期望(也许是4000,但为简便起见,此处为30):
select *
from xmltable (
'/row'
passing xmltype('<row id="124">
<c1>Name</c1>
<c2>Name2</c2>
</row>')
columns
col1 varchar2(30) path '*[1]',col2 varchar2(30) path '*[2]',col3 varchar2(30) path '*[3]'
);
COL1 COL2 COL3
------------------------------ ------------------------------ ------------------------------
Name Name2
然后您可以取消透视以获取您声明的输出,再次使用与XMLTable unpivot
子句一样多的columns
子句:
select result
from xmltable (
'/row'
passing xmltype('<row id="124">
<c1>Name</c1>
<c2>Name2</c2>
</row>')
columns
col1 varchar2(30) path '*[1]',col3 varchar2(30) path '*[3]'
)
unpivot (result for x in (col1 as 1,col2 as 2,col3 as 3));
RESULT
------------------------------
Name
Name2
您还可以对每一行进行单独的XMLQuery调用,然后将它们合并在一起,但这看起来更复杂且效率更低。
如果您的数据在表中,则可以对其进行扩展-在此处使用CTE来代表该表:
with your_table(xml_col) as (
select xmltype('<row id="124">
<c1>Name</c1>
<c2>Name2</c2>
</row>')
from dual
union all
select xmltype('<row id="125">
<x>Value X</x>
<y>Value Y</y>
<z>999</z>
</row>')
from dual
)
select id,result
from your_table t
cross join xmltable (
'/row'
passing t.xml_col
columns
id number path '@id',col1 varchar2(30) path '*[1]',col3 varchar2(30) path '*[3]'
) x
unpivot (result for x in (col1 as 1,col3 as 3));
ID RESULT
---------- ------------------------------
124 Name
124 Name2
125 Value X
125 Value Y
125 999
您还可以扩展它以包括原始节点名称,这可能有助于理解值:
with your_table(xml_col) as (
...
)
select id,col,col1_name varchar2(30) path '*[1]/local-name()',col2_name varchar2(30) path '*[2]/local-name()',col3_name varchar2(30) path '*[3]/local-name()',col3 varchar2(30) path '*[3]'
) x
unpivot (
(col,result) for x in (
(col1_name,col1) as 1,(col2_name,col2) as 2,(col3_name,col3) as 3
)
);
ID COL RESULT
---------- ------------------------------ ------------------------------
124 c1 Name
124 c2 Name2
125 x Value X
125 y Value Y
125 z 999
db<>fiddle,尽管正在运行的版本似乎在显示表的中间结果(取消透视前)时出现了错误,所以我为它们显示了表和CTE。