我有XML数据,其中父子关系是根据XML中的位置维护的(子元素属于上一个父元素,直到看到下一个父元素)。可以用XMLTable()
来实现吗?
考虑以下示例XML
<myData>
<myParent>
<parentID>H1</parentID>
<parentName>Header 1</parentName>
</myParent>
<myChild>
<childID>D1</childID>
<childName>Detail D1</childName>
</myChild>
<myChild>
<childID>D2</childID>
<childName>Detail D2</childName>
</myChild>
<myParent>
<parentID>H2</parentID>
<parentName>Header 2</parentName>
</myParent>
<myChild>
<childID>D3</childID>
<childName>Detail D3</childName>
</myChild>
</myData>
我想要的是
PARENTID CHILDID CHILDNAME
----------- ----------- ----------------------
H1 D1 Detail D1
H1 D2 Detail D2
H2 D3 Detail D3
最好的方法是使用select语句,尽管其他方法(例如,table function,ref cursor)也很有帮助。
我可以将父项和子项分别提取为表。但是,由于XML的设计,我找不到键来连接它们。
with xml as (
select xmltype(
'<myData>
<myParent>
<parentID>H1</parentID>
<parentName>Header 1</parentName>
</myParent>
<myChild>
<childID>D1</childID>
<childName>Detail D1</childName>
</myChild>
<myChild>
<childID>D2</childID>
<childName>Detail D2</childName>
</myChild>
<myParent>
<parentID>H2</parentID>
<parentName>Header 2</parentName>
</myParent>
<myChild>
<childID>D3</childID>
<childName>Detail D3</childName>
</myChild>
</myData>') data
from dual
)
select child.* from xml,
--XMLTable for header
--xmltable('myData/myParent' passing
--xml.data
--columns row_num for ordinality,
-- "parentID",
-- "parentName"
--) parent,
--XMLTable for detail
xmltable('myData/myChild' passing
xml.data
columns row_num for ordinality,
"childID",
"childName"
) child;
db<>fiddle
这将唯一的子元素输出为一个表。(注解输出部分是另一个XMLTable()
,用于提取父级。但是,两者没有办法结合)
3条答案
按热度按时间kqlmhetl1#
可以使用LAST_VALUE在子元素之前获取最近的父元素(按row_num):
cidc1ykv2#
为了回答附属问题“如果父元素和子元素中的内部标记名称相同怎么办”:
yqyhoc1h3#
作为一个框架挑战,不要像那样格式化XML。相反,将子对象嵌套在父对象中:
然后您可以使用:用途:
其输出:
| 行数|parentId| PARENTNAME|行数|儿童|儿童姓名|
| --|--|--|--|--|--|
| 1 |H1|集管1| 1 |D1|详图D1|
| 1 |H1|集管1| 2 |D2|详图D2|
| 2 |H2|集流管2| 1 |D3|详图D3|
fiddle
理论上,使用您的格式,您将获得前面的
myParent
兄弟,并可以使用查询:但是,Oracle似乎不支持
preceding-sibling::*
语法,因此parent*
列都作为NULL
返回,不幸的是,查询不起作用。fiddle