【问题标题】:how can I select XML attribute from oracle XMLTYPE column?如何从 oracle XMLTYPE 列中选择 XML 属性?
【发布时间】:2020-08-07 12:34:22
【问题描述】:

我像这样在 oracle 12c 中创建表

CREATE TABLE Test_xml
    (
       xml_data                       SYS.XMLTYPE
    )

并将这样的 XML 数据插入 xml_data 列中

<?xml version="1.0" encoding="UTF-8"?>
<persons xmlns="http://XXXXX.XXX/schema/1.0" name="ABC">
  <person>
    <name1 value="AAAA" />
    <name2 value="CCCC" />
    <name3 value="XXXX" />
  </person>
  <person>
    <name1 value="11111" />
    <name2 value="22222" />
    <name3 value="33333" />
  </person>
</persons>

但是当我尝试通过查询从表中选择数据时

SELECT xt.*
FROM   Test_xml x,
       XMLTABLE('/persons/person'
         PASSING x.xml_data
         COLUMNS 
           name1  VARCHAR2(2000) PATH 'name1/@value'
         ) xt;

查询中没有问题,我如何从表中选择 name1?

【问题讨论】:

    标签: sql xml oracle


    【解决方案1】:

    您可以提供(在这种情况下为默认)命名空间作为 XMLTable 的另一个参数:

    SELECT xt.*
    FROM   Test_xml x,
           XMLTABLE(
             xmlnamespaces(default 'http://XXXXX.XXX/schema/1.0'),
             '/persons/person'
             PASSING x.xml_data
             COLUMNS 
               name1  VARCHAR2(2000) PATH 'name1/@value'
             ) xt;
    
    | NAME1 |
    | :---- |
    | AAAA  |
    | 11111 |
    

    db<>fiddle 显示您的原始查询、@Sayan 的通配符版本(由于某种原因,它会为空,即使它适用于 CTE),以及此默认命名空间版本。

    【讨论】:

      【解决方案2】:

      只需将/persons/person 替换为/*:persons/*:person

      SELECT/*+ NO_XML_QUERY_REWRITE */ xt.*
      FROM   Test_xml x,
             XMLTABLE('/*:persons/*:person'
               PASSING x.xml_data
               COLUMNS 
                 name1  VARCHAR2(2000) PATH '*:name1/@value'
               ) xt;
      

      完整示例:

      with test_xml(xml_data) as (
      select xmltype(q'[<?xml version="1.0" encoding="UTF-8"?>
      <persons xmlns="http://XXXXX.XXX/schema/1.0" name="ABC">
        <person>
          <name1 value="AAAA" />
          <name2 value="CCCC" />
          <name3 value="XXXX" />
        </person>
        <person>
          <name1 value="11111" />
          <name2 value="22222" />
          <name3 value="33333" />
        </person>
      </persons>]'
      )
      from dual
      )
      SELECT xt.*
      FROM   Test_xml x,
             XMLTABLE('/*:persons/*:person'
               PASSING x.xml_data
               COLUMNS 
                 name1  VARCHAR2(2000) PATH '*:name1/@value'
               ) xt;
      
      NAME1
      --------------------
      AAAA
      11111
      

      【讨论】:

      • 我试试你的查询 当它从对偶中选择时它工作,但如果应用于表,name1 的结果为空,但返回表中正确的行数。我错过了什么吗?
      • @maxzzxam 你注意到*:name1/@value了吗?
      • @SayanMalakshinov - 我在我的数据库中包含了你的通配符版本fiddle;它在桌子上不起作用。不知道为什么,或者为什么它会表现不同。转储 XML 显示相同的数据类型 (58) 但长度不同。
      • @AlexPoole 嗯!您在 columns 子句中发现了一个错误 :) 我在您的 dbfiddle 中包含了另一个变体:dbfiddle.uk/…
      • Re“不同的长度”:虽然这不好,但可以理解:oracle 自 11.2 以来默认使用二进制 xml 存储
      猜你喜欢
      • 2013-03-02
      • 1970-01-01
      • 1970-01-01
      • 2011-06-15
      • 2019-07-07
      • 1970-01-01
      • 1970-01-01
      • 2015-08-12
      • 1970-01-01
      相关资源
      最近更新 更多