我使用EXTRACT方法从Oracle 11g数据库中的XML类型列中提取值。
如果我的桌子有10行, 因为EXTRACT用在select子句中,当我在XPATH中添加一些条件时,如
'/Items/OperatingSystem/@Version[contains(.,"4.04")]'
在返回的行中,如果XPATH表达式不匹配,则显示null,但它显示所有10行。
所以我试图转移到XMLTABLE,因为我发现这是最新的(EXTRACT已被弃用)我们知道它在FROM子句中使用。我尝试了几个基本查询,发现它只返回与XPATH表达式匹配的行。(跳过在EXTRACT情况下返回的空行)
我发现使用XMLTABLE的一个奇怪问题是 - 在我的本地环境中,当我使用XPATH表达式
时'/Items/OperatingSystem/@Version[contains(.,"4.04")]'
结果,它只选择名称中包含'Dee'的行。
但是当我针对我们的测试环境运行相同的查询时
它选择所有行而不是仅选择名称包含'Dee'。 我找不到任何暗示为什么会发生这种情况。我尝试了更多的查询将条件放在其他字段,如Age等..但结果是相同的。它将返回所有行。
以下是版本详情 - 本地Oracle版本 -
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
"CORE 11.2.0.2.0 Production"
TNS for 64-bit Windows: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production
测试环境Oracle版本 -
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
"CORE 11.2.0.3.0 Production"
TNS for HPUX: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production
这些版本中是否有与XMLTABLE相关的更改。
示例数据
假设我有下表
NAME | XMLDATA | CRT_TS
Ubuntu | UbuntuXMLDATA | 20-OCT-2016
Windows | WindowsXMLDATA| 20-OCT-2016
UbuntuXMLDATA
<Items>
<OperatingSystem Name="Ubuntu 12.04" Version="12.04" />
<OperatingSystem Name="Ubuntu 14.04" Version="14.04" />
<OperatingSystem Name="Ubuntu 16.04" Version="16.04" />
</Items>
WindowsXMLDATA
<Items>
<OperatingSystem Name="Windows" Version="8" />
<OperatingSystem Name="Windows" Version="7" />
</Items>
在表格中,上面的xmls存在于XMLDATA列中。
查询
select Name,rx.COLUMN_VALUE as XPATH_OUTPUT from Operating_System, XMLTABLE('/Items/OperatingSystem/@Version[contains(.,"4.04")]' PASSING XMLTYPE(XMLDATA)) rx where CRT_TS = 20-OCT-2016;
预期结果
Name | XPATH_OUTPUT
Ubuntu | 14.04
实际结果
Name | XPATH_OUTPUT
Ubuntu | 12.04
Ubuntu | 14.04
Ubuntu | 16.04
我面临的问题是上面的查询在我的本地数据库中正常工作。 但是对于测试环境它返回三行而不是一行。我无法弄清楚为什么?是由于Oracle版本(我已经给出了上面的详细信息)不匹配?
答案 0 :(得分:1)
我不确定它是不是一个bug。 在xmltable中,如果您没有使用别名来传递xml。 ”。”是xml的根。
试试这个xpath。
'/Items/OperatingSystem/@Version[contains(.,"4.04")]'
'/Items/OperatingSystem/@Version[contains(.,"OperatingSystem")]'
'/Items/OperatingSystem/@Version[contains(.,"Ubuntu")]'
结果总是如此。 3排。
包含(。,“xxxx”)]检查整个文档是否包含字符串
解决方案1
更改xquery。
'/Items/OperatingSystem[contains(@Version,"14.04")]/@Version'
解决方案2
为xml添加别名。
XMLTABLE('$doc/Items/OperatingSystem/@Version[contains(.,"4.04")]' PASSING XMLTYPE(XMLDATA) as "doc")
答案 1 :(得分:0)
对于遇到类似问题的任何人,我都可以通过更改XPATH表达式来解决问题。将XPATH表达式更新为
/Items/OperatingSystem[contains(@Version,"4.04")]/@Version
不是使用点(。)运算符来获取当前属性的值,而是给@Version本身。