【问题标题】:ORACLE Parsing XML string into separate recordsORACLE 将 XML 字符串解析为单独的记录
【发布时间】:2013-01-20 04:29:33
【问题描述】:

我正在尝试查找多个组的成员。组成员身份作为 XML 存储在 ORACLE 数据库中。我需要一个 SQL 查询来将每个成员分成单独的行。

我看过一些关于使用 xmlsequence 的帖子,但由于缺乏理解而没有成功。

一个示例字符串是

<D:href xmlns:D='DAV:'>/users/admin@Native Directory</D:href>
<D:href xmlns:D='DAV:'>/users/oracle@Native Directory</D:href>
<D:href xmlns:D='DAV:'>/users/user1@DomainProd</D:href>

我目前的结果是

Group       User
-------------------------------------------------------------------------
group1      <D:href xmlns:D='DAV:'>/users/admin@Native Directory</D:href>
            <D:href xmlns:D='DAV:'>/users/oracle@Native Directory</D:href>
            <D:href xmlns:D='DAV:'>/users/user1@DomainProd</D:href>
group2      <D:href xmlns:D='DAV:'>/users/admin@Native Directory</D:href>
            <D:href xmlns:D='DAV:'>/users/oracle@Native Directory</D:href>
            <D:href xmlns:D='DAV:'>/users/user1@DomainProd</D:href>
group3      <D:href xmlns:D='DAV:'>/users/admin@Native Directory</D:href>
            <D:href xmlns:D='DAV:'>/users/oracle@Native Directory</D:href>
            <D:href xmlns:D='DAV:'>/users/user1@DomainProd</D:href>

我希望我的结果集是

Group       User
-------------------
group1      admin
group1      oracle
group1      user1
group2      admin
group2      oracle
group2      user1
group3      admin
group3      oracle
group3      user1

任何帮助将不胜感激......

谢谢

【问题讨论】:

标签: sql xml oracle


【解决方案1】:

您可以使用 XMLTABLE。由于您的 XML 文档似乎是行中的一个片段,因此我将其包装在 &lt;root&gt; 元素中。

select grp, substr(name, 
              instr(name, '/', -1) + 1,
              instr(name, '@') - instr(name, '/', -1) - 1
             ) name
  from mytab m, 
       xmltable(xmlnamespaces('DAV:' as "D"), 
                '/root/D:href' passing xmltype('<root>'||usr||'</root>')
                columns
                name varchar2(200) path './text()');

我假设您的 xml 列存储为名为 (usr) 的 clob/varchar2 的表。

group1 的示例输出:

SQL> select grp, substr(name,
  2                instr(name, '/', -1) + 1,
  3                instr(name, '@') - instr(name, '/', -1) - 1
  4               ) name
  5    from mytab m,
  6         xmltable(xmlnamespaces('DAV:' as "D"),
  7                  '/root/D:href' passing xmltype('<root>'||usr||'</root>')
  8                  COLUMNS
  9                  name VARCHAR2(200) path './text()');

GRP    NAME
------ ----------
group1 admin
group1 oracle
group1 user1

http://sqlfiddle.com/#!4/435cd/1

【讨论】:

  • 谢谢@DazzaL。它在 sqlfiddle 上工作,但不在服务器上。我得到 ORA-19102: XQuery string literal expected. 我正在使用它的查询select X.name from PROPERTIES p, xmltable(xmlnamespaces('DAV:' as "D"), '/root/D:href' passing xmltype('&lt;root&gt;'||p.PROPERTY_VALUE||'&lt;/root&gt;') COLUMNS name CLOB PATH './text()') X'
  • @5hak3y 这可能是因为您将 CURSOR_SHARING 设置为 FORCE 或 SIMILAR。你能确认一下吗?一种简单的查看方式是在select /*+ cursor_sharing_exact */ grp 中添加此提示
【解决方案2】:

@DazzaL's answer 是一个不错的选择(在大多数情况下可能更快),
但你也可以这样做:

with tt as 
(select ggroup, regexp_replace(uuser, '([[:print:]]*)(/users/)([[:alnum:]]*)(@)([[:print:]]*)','\3,') user_csv
from t)
select distinct ggroup, regexp_substr(user_csv,'[^,]+',1,level)
from tt
connect by regexp_substr(user_csv,'[^,]+',1,level) is not null
order by ggroup

t 在我的查询中是表的名称

Here is a sqlfiddle demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多