我在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;
不确定是否还需要在查询中传递其他内容?
答案 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
如果您想在同一个查询中获取其他数据,可以将这些数据添加为更多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文档(以及大量的他们可能没有显着的性能差异。