我有一些看起来很像下面这样的XML数据:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<context>
<docNbr>
1234
</docNbr>
<thisType>
我想要做的是使用一个表别名,它只在某个类型存在时才从这个XML中选择字段(我想在使用WHERE子句时使用XMLExists或ExistsNode,但没有成功)。这样我就可以有条件地在两个不同的XML片段之间呈现数据。例如,我可能有这样的数据:
<data>
<context>
<docNbr>
1234
</docNbr>
<thatType>
下面是本例中我的两个别名表:
thisType as (
SELECT x.xml_id, c.*,
'thisType' as type
FROM xml x,
XMLTABLE('//data'
PASSING x.data
COLUMNS
docNbr PATH '//context/docNumber'
WHERE XMLEXISTS('$INFO//data/context/thisType'
passing x.data as "INFO")
) c
),
thatType as (
SELECT x.xml_id, c.*,
'thatType' as type
FROM xml x,
XMLTABLE('//data'
PASSING x.data
COLUMNS
docNbr PATH '//context/docNumber'
,specialValue PATH '//moreData/subData/specialID'
WHERE XMLEXISTS('$INFO//data/context/thatType'
passing x.data as "INFO")
) c
)
其思想是在这两个表之间使用UNION ALL,以便其中一个根据出现的子"type“节点选择另一个。
然而,当我尝试以这种方式使用XMLExists时,我在整个SQL中得到了一个“缺少右括号”。
有没有人能告诉我还能尝试些什么?
发布于 2021-01-19 04:42:14
您必须将WHERE子句放在正确的位置。
WITH
thisType AS ( SELECT x.xml_id,
c.*,
'thisType' as type
FROM xml x,
XMLTABLE('//data'
PASSING x.data
COLUMNS
docNbr PATH '//context/docNbr'
) c
WHERE XMLEXISTS('$INFO//data/context/thisType'
PASSING x.data as "INFO")
),
thatType AS ( SELECT x.xml_id,
c.*,
'thatType' as type
FROM xml x,
XMLTABLE('//data'
PASSING x.data
COLUMNS
docNbr PATH '//context/docNbr',
specialValue PATH '//moreData/subData/specialID'
) c
WHERE XMLEXISTS('$INFO//data/context/thatType'
PASSING x.data as "INFO")
)
SELECT xml_id,
type,
docNbr,
NULL AS specialValue
FROM thisType
UNION ALL
SELECT xml_id,
type,
docNbr,
specialValue
FROM thatType;
但在我看来,它可以更简单:
SELECT x.xml_id,
c.*,
COALESCE(thisType, thatType) as type
FROM xml x,
XMLTABLE('//data'
PASSING x.data
COLUMNS
docNbr PATH '//context/docNbr',
thisType PATH '//context/thisType',
thatType PATH '//context/thatType',
specialValue PATH '//moreData/subData/specialID'
) c
此外,我还建议您更好地命名列和别名。特别是,不要使用Oracle关键字。
https://stackoverflow.com/questions/65242901
复制相似问题