ExtractXML Oracle Query返回Null

时间:2017-12-08 14:50:29

标签: sql xml oracle

我在Oracle 12c数据库的表“data”的“属性”列中有以下数据:

<Attributes>
  <Map>
    <entry key="accountFlags">
      <value>
        <List>
          <String>Normal User Account</String>
        </List>
      </value>
    </entry>
    <entry key="cn" value="paul.john"/>
    <entry key="department" value="IT"/>
    <entry key="description" value="New account. Automatically created"/>
    <entry key="displayName" value="John, Paul"/>
    <entry key="distinguishedName" value="CN=paul.john,OU=Users,DC=test,DC=com"/>
    <entry key="givenName" value="Paul"/>
    <entry key="homeMDB" value="CN=Test,CN=Databases,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=test,DC=com"/>
    <entry key="l" value="London"/>
    <entry key="mail" value="paul.john@test.com"/>
    <entry key="mailNickname" value="PaulJ"/>
    <entry key="manager" value="CN=brock.lesnar,OU=Users,DC=test,DC=com"/>
    <entry key="memberOf">
      <value>
        <List>
          <String>CN=Test1,OU=Rights,OU=Groups,DC=test,DC=com</String>
          <String>CN=Test2,OU=Rights,OU=Groups,DC=test,DC=com</String>
          <String>CN=Test3,OU=Rights,OU=Groups,DC=test,DC=com</String>
          <String>CN=Test4,OU=Rights,OU=Groups,DC=test,DC=com</String>
        </List>
      </value>
    </entry>
  </Map>
</Attributes>

我希望从此列中提取“memberOf”的值,如下所示:

MEMBER_OF
---------
CN=Test1,OU=Rights,OU=Groups,DC=test,DC=com
CN=Test2,OU=Rights,OU=Groups,DC=test,DC=com
CN=Test3,OU=Rights,OU=Groups,DC=test,DC=com
CN=Test4,OU=Rights,OU=Groups,DC=test,DC=com

我已尝试使用以下查询返回null:

SELECT EXTRACTVALUE(xmltype(attributes), '/Attributes/Map/entry[@key="memberOf"]/value/List/@String')
FROM DATA;

我也尝试了下面的查询,它也返回null

SELECT EXTRACTVALUE(xmltype(attributes), '/Attributes/Map/entry[@key="memberOf"]/value[1]/List/@String')
FROM DATA;

不确定是否还需要在查询中传递其他内容?

2 个答案:

答案 0 :(得分:1)

试试这个

SELECT y.*
  FROM (SELECT *
          FROM XMLTABLE ('/Attributes/Map/entry[@key="memberOf"]/value/List'
                         PASSING (SELECT xmltype (attributes)
                                    FROM data)
                         COLUMNS strings XMLTYPE PATH 'String')) x,
       XMLTABLE ('/String'
                 PASSING x.strings
                 COLUMNS memberOf VARCHAR (300) PATH '.') y;

答案 1 :(得分:1)

您的路径以.../@String结尾,String正在寻找名为ORA-19025: EXTRACTVALUE returns value of only one node 的属性,而不是节点。但是,如果你解决了这个问题,那么:

XMLQuery()

ExtractValue() is long-deprecated anyway。您可以使用select xmlquery('/Attributes/Map/entry[@key="memberOf"]/value/List/String' passing xmltype(attributes) returning content) as member_of from data; MEMBER_OF -------------------------------------------------------------------------------- <String>CN=Test1,OU=Rights,OU=Groups,DC=test,DC=com</String><String>CN=Test2,OU= Rights,OU=Groups,DC=test,DC=com</String><String>CN=Test3,OU=Rights,OU=Groups,DC= test,DC=com</String><String>CN=Test4,OU=Rights,OU=Groups,DC=test,DC=com</String> 代替,但这会为您提供单个XML片段而不是单独的字符串:

XMLTable()

相反,使用select x.member_of from data cross join XMLTable('/Attributes/Map/entry[@key="memberOf"]/value/List/String' passing XMLType(attributes) columns member_of varchar2(60) path '.' ) x; MEMBER_OF ------------------------------------------------------------ CN=Test1,OU=Rights,OU=Groups,DC=test,DC=com CN=Test2,OU=Rights,OU=Groups,DC=test,DC=com CN=Test3,OU=Rights,OU=Groups,DC=test,DC=com CN=Test4,OU=Rights,OU=Groups,DC=test,DC=com 来获取各个值,正如Bikash建议的那样 - 但是可以更简单地完成,而不需要两个XMLTable调用:

columns

Read more

如果您想在同一个查询中获取其他数据,可以将这些数据添加为更多select x.* from data cross join XMLTable('/Attributes/Map/entry[@key="memberOf"]/value/List/String' passing XMLType(attributes) columns cn varchar2(20) path './../../../../entry[@key="cn"]/@value', department varchar2(10) path './../../../../entry[@key="department"]/@value', member_of varchar2(60) path '.' ) x; CN DEPARTMENT MEMBER_OF -------------------- ---------- ------------------------------------------------------------ paul.john IT CN=Test1,OU=Rights,OU=Groups,DC=test,DC=com paul.john IT CN=Test2,OU=Rights,OU=Groups,DC=test,DC=com paul.john IT CN=Test3,OU=Rights,OU=Groups,DC=test,DC=com paul.john IT CN=Test4,OU=Rights,OU=Groups,DC=test,DC=com 子句,引用备份树 - 因为其余的是单个节点,除非您有并且需要显示多个帐户标志。

select x1.cn, x1.department, x2.member_of
from data
cross join XMLTable('/Attributes/Map'
  passing XMLType(attributes)
  columns cn varchar2(20) path 'entry[@key="cn"]/@value',
    department varchar2(10) path 'entry[@key="department"]/@value',
    member_of_xml XMLType path 'entry[@key="memberOf"]'
) x1
cross join XMLTable('/entry/value/List/String'
  passing member_of_xml
  columns member_of varchar2(60) path '.'
) x2;

虽然一旦你这样做,如果你使用多个XMLTable调用,它可能更容易阅读和维护:

'$username'

然后添加第三个XMLTable调用来处理多个帐户标记很简单。

您也可以在单个XMLTable中使用带有循环等的更复杂的XPath进行所有这些操作,但我认为这更清晰,更简单,除非您处理大型XML文档(以及大量的他们可能没有显着的性能差异。