oracle XMLTABLE未按预期工作

时间:2016-10-20 14:57:25

标签: oracle xpath oracle11g xmltable

我使用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版本(我已经给出了上面的详细信息)不匹配?

2 个答案:

答案 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本身。