Oracle 使用XMLTABLE和xquery从xml中提取数据

Oracle 使用XMLTABLE和xquery从xml中提取数据,oracle,plsql,xquery,xmltable,Oracle,Plsql,Xquery,Xmltable,我有以下一段XML: <per:Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.something.com/2014/11/bla/webservice.xsd" xmlns:per="http://www.something.com/2014/11/bla/person"> <per:Initials>E.C.&

我有以下一段XML:

<per:Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.something.com/2014/11/bla/webservice.xsd"
    xmlns:per="http://www.something.com/2014/11/bla/person">
    <per:Initials>E.C.</per:Initials>
    <per:FirstName>Erik</per:FirstName>
    <per:LastName>Flipsen</per:LastName>
    <per:BirthDate>1980-07-01</per:BirthDate>
    <per:Gender>Male</per:Gender>
</per:Person>
我对名称空间使用通配符,因为我并不真正关心发送方对名称空间使用的缩写,我知道获取数据的确切路径

有了这段代码,我就有两件事困扰着我:

  • 根据文档,路径应该是可选的,但是,一旦我从COLUMNS部分删除了路径,我就不会再得到任何结果
编辑:

我发现,当我删除元素的名称空间并使其大写时,它就起作用了。因此,似乎列名需要与xml元素名匹配才能使其正常工作。我还没有弄明白如何使它与名称空间的XML一起工作

  • 文档还指出“对于除For ORDINALITY列之外的每个结果列,必须指定列数据类型”,但是,如果没有它,它似乎可以正常工作。为列和我将数据提取到的变量指定它似乎有点多余。如果不指定数据类型,会给我带来麻烦吗
可运行代码示例:

SET SERVEROUTPUT ON;
DECLARE

    pxRequest xmltype := xmltype('<per:Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                    xsi:schemaLocation="http://www.something.com/2014/11/bla/webservice.xsd"
                                    xmlns:per="http://www.something.com/2014/11/bla/person">
                                    <per:Initials>E.C.</per:Initials>
                                    <per:FirstName>Erik</per:FirstName>
                                    <per:LastName>Flipsen</per:LastName>
                                    <per:BirthDate>1980-01-01</per:BirthDate>
                                    <per:Gender>Male</per:Gender>
                                </per:Person>');
    lsInitials  varchar2(100);
    lsFirstname varchar2(100);                                


begin

    select pers.Initials,
           pers.Firstname
        into lsInitials,
             lsFirstname
        from
        XMLTABLE ('*:Person' passing pxRequest
        columns Initials           PATH '*:Initials',
                Firstname          PATH '*:FirstName'
        )  pers;


    dbms_output.put_line(lsInitials);
    dbms_output.put_line(lsFirstname);

end;                            
打开服务器输出;
声明
pxRequest xmltype:=xmltype('
E.C。
埃里克
弗利普森
1980-01-01
男性
');
l初始varchar2(100);
lsFirstname varchar2(100);
开始
选择个人姓名首字母,
姓名
进入初始阶段,
lsFirstname
从…起
XMLTABLE(“*:Person”传递请求
列初始值路径“*:初始值”,
名字路径“*:名字”
)pers;
dbms_output.put_line(lsInitials);
dbms_output.put_行(lsFirstname);
结束;
参考资料:

如果您在xmltable中加载命名空间元素,它应该可以正常工作:

select results    
from xmltable( 
  xmlnamespaces(
    default 'http://tempuri.org/',    
    'http://schemas.xmlsoap.org/soap/envelope/' as "soap" 
  ),    
  'soap:Envelope/soap:Body/addResponse' passing xmltype(v_xml) 
   columns results varchar(100) path './addResult')
根据您的示例(您可能还需要提前注册架构/命名空间,但这应该是一次):


以前在Oracle版本中使用的东西在11g+中对XML不起作用,正如我所看到的,Oracle强烈验证/键入XML操作的输入/输出,在以前的版本中,您可以在没有命名空间信息的情况下运行正常的XQuery操作

根据您的第一个问题,今天有关于省略路径的问题吗

可选的
PATH
子句指定由XQuery表达式字符串寻址的XQuery结果部分将用作列内容

如果省略
路径
,则假定XQuery表达式列。例如:

(…列xyz)

相当于

XMLTable(…列xyz路径'xyz')

可以使用不同的PATH子句将XQuery结果拆分为不同的虚拟表列

之所以假定列
xyz
'xyz'
,是因为Oracle默认不区分大小写(默认为所有大写)。如果将列定义为
“aBcD”
,则将假定
路径值为
“aBcD”


至于关于指定数据类型的第二个问题:如果您提取的数据总是文本数据,那么您可能不需要指定数据类型

然而,如果您开始处理诸如日期、时间戳、浮点数等问题,那么您可能会遇到问题。您需要使用
函数手动将它们转换为*
函数,也可以在列定义中指定它们的数据类型。如果您不这样做,Oracle可以自由地隐式转换它,无论它感觉如何合适,这可能会产生意想不到的后果

select results    
from xmltable( 
  xmlnamespaces(
    default 'http://tempuri.org/',    
    'http://schemas.xmlsoap.org/soap/envelope/' as "soap" 
  ),    
  'soap:Envelope/soap:Body/addResponse' passing xmltype(v_xml) 
   columns results varchar(100) path './addResult')
select pers.Initials,
       pers.Firstname
    into lsInitials,
         lsFirstname
    from
    XMLTABLE (
      xmlnamespaces(
        default 'http://tempuri.org/',   
        'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
        'http://www.something.com/2014/11/bla/person' as "per" 
      ),
    passing pxRequest
    columns Initials           PATH '*:Initials',
            Firstname          PATH '*:FirstName'
    )  pers;