|
下面的示例分四步进行了说明。
1. 首先,在目录 XML_DIR 下的文件 invoiceformtest.xsd 中创建一个模式定义。该清单如下所示:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xdb=http://xmlns.oracle.com/xdb version="1.0"> <xs:element name="INVOICEFORMTEST" xdb:def***tTable="INVOICEFORMTEST"> <xs:complexType> <xs:sequence> <xs:element name="MailAddressTo"> <xs:complexType> <xs:sequence> <xs:element name="Person" type="xs:string"/> <xs:element name="Street" type="xs:string"/> <xs:element name="City" type="xs:string"/> <xs:element name="State" type="xs:string"/> <xs:element name="Zipcode" type="xs:string"/> </xs:sequence> <xs:attribute name="id" type="xs:string" use="required"/> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
2. 使用过程 DBMS_XMLSCHEMA.registerSchema 在数据库中注册上面的模式。您用来连接到数据库的用户名需要修改会话权限,以便该模式可以成功注册。
BEGIN DBMS_XMLSCHEMA.registerSchema( SCHEMAURL => 'http://xmlns.oracle.com/xdb/invoiceformtest.xsd', SCHEMADOC => bfilename('XMLDIR','invoiceformtest.xsd'), CSID => nls_charset_id('AL32UTF8')); END; /
要删除该模式,只需运行 DBMS_XMLSCHEMA.deleteSchema 语句,如下所示:
BEGIN DBMS_XMLSCHEMA.deleteSchema( SCHEMAURL => 'http://xmlns.oracle.com/xdb/invoiceformtest.xsd', DELETE_OPTION => dbms_xmlschema.DELETE_CASCADE_FORCE); END; /
3. 由于上面模式定义中的 xdb:def***tTable="INVOICEFORMTEST" 语句,以上语句还创建了表 invoiceformtest。没有它,将创建一个生成的名称(您不想使用该名称)。
4. 现在,我们准备将文档输入到 XML 文档内基于 XMLSchema 的表中,该文档存储在 XML_DIR 中并使用实现的模式指定的格式。
Insert into invoiceformtest values (XMLType(bfilename('XMLDIR', 'invoiceformtest.txt'), nls_charset_id(' AL32UTF8')));
来看一下我们刚刚使用 XML 文档上的 object_value pseudocolumn 创建的内容。
SQL> select object_value from invoiceformtest;
OBJECT_VALUE <INVOICEFORMTEST> <MailAddressTo id="1"> <Person>Joe Smith</Person> <Street>10 Apple Tree Lane</Street> <City>New York</City> <State>NY</State> <Zipcode>12345</Zipcode> </MailAddressTo> </INVOICEFORMTEST>
完成! 了解 XQuery 函数和表达式
XQuery 是 W3C 针对查询语言开发的一个标准,用于从 XML 文件提取信息。它允许我们访问物理 XML 文档或者通过 XML 视图虚拟化为 XML 文档的关系数据。使用的表达式可以是简单的查询或较大查询的一部分,而且可以包括标准函数,例如,日期/时间、算术或字符串函数以及用户定义的函数。 XQuery 是 Oracle 数据库 10g 第 2 版中的新特性,并受 XMLQuery() 和 XMLTable() 函数支持。使用这两个函数的示例稍后在“XMLQuery() 和 XMLTable()”部分中有述。
XQuery 使用 XPath 表达式(如下所述)定位 XML 文档中的详细项。可将其看作是 Oracle 数据库 10g 第 2 版中引入的 XMLQuery() 和 XMLTable() 函数的基础,本文稍后有述。
以下将介绍一些更重要的 XQuery 表达式(包括 XPath、XMLSequence 和 FLWOR)。 XPath、XMLSequence 和 FLWOR 表达式
XPath。XPath 提供使用定址技术在 XML 文档中定位项的方式,而且它通过一个文档结构使用逻辑路径处理这些项。它允许程序员在较高的抽象级别处理文档,方法是通过文档指定路由而非指向特定元素。 XPath 使用节点概念定义路径在何处开始,然后定义一个“逻辑树”,该树包括诸如 attribute、self、parent、child 和 ancestor 等关系。换言之,XPath 会将 XML 文档建模为节点树。节点类型分为若干种,例如,元素节点、属性节点和文本节点。XPath 可以确定一个方式来为每个节点计算字符串值。
凭借 XPath 表达式,您可使用基于标准的方式查询和更新 XML 文档。我们将使用 extract、extractValue、existsNode 和 XMLSequence 函数来演示 XPath 功能,期间将用到我们已创建的 invoicexml_tbl 文档以及插入到其中的数据。
查询要在 XPath 示例中使用的文档。让我们看一下如何使用 XPath 函数通过 SQL 搜索 XML (XMLType) 数据。为此,来看一下要使用 object_value pseudocolumn 从 XMLType 表检索 XML 文档时涉及的文档。
SQL> select object_value from invoicexml_tbl;
OBJECT_VALUE <Invoice> <MailAddressTo id="PA"> <Person>Joe Smith</Person> <Street>10 Apple Tree Lane</Street> <City>New York</City> <State>NY</State> <Zipcode>12345</Zipcode> </MailAddressTo> <MailAddressFrom id="PA"> <Person>Ed Jones</Person> <Street>11 Cherry Lane</Street> <City>Newark</City> <State>NJ</State> <Zipcode>67890</Zipcode> </MailAddressFrom> <Details id="2006Sept1to30PA"> <FromTo>Sept 1, 2006 to Sept 30, 2006</FromTo> <Hours>70</Hours> <Rate>30</Rate> <Taxes>210</Taxes> <TotalDue>2310</TotalDue> <InvDate>Oct 1, 2006</InvDate> <Contractor>Ed Jones</Contractor> </Details> </Invoice>
使用 extract。使用 extract 时,通过将 extract 与 object_value 合并,可从文档选择单个节点及其叶节点。换言之,我们可以查看存储为 XMLType 的 XML 文档。无论我们使用的是结构化数据还是非结构化数据以及数据是否基于模式,情况都是如此。开始提取 MailAddressTo 节点及其叶节点。
select extract(object_value, '/Invoice/MailAddressTo') from invoicexml_tbl;
EXTRACT(OBJECT_VALUE,'/INVOICE/MAILADDRESSTO') <MailAddressTo id="PA"><Person>Joe Smith</Person><Street>10 Apple Tree Lane</Street><City>New York</City><State>NY</Stat e><Zipcode>12345</Zipcode></MailAddressTo>
如您所见,该输出包括文档的 MailAddressTo 部分,不适合打印(格式化)。此外,用于实现它的语法非常简单。重要的是,我们能够在无需转储整个内容的情况下查看文档。
使用 extractValue。叶节点中存在的数据值可以使用 extractValue 提取。较高级的节点(例如 MailAddressTo)无法使用该函数提取。请注意,它的输出不是 XML 语法格式,其中只包含该数据值。
select extractValue(object_value, '/Invoice/MailAddressTo/Person') Person from invoicexml_tbl;
PERSON Joe Smith
使用 existsNode。ExistsNode 以类似的方式使用,以便在节点级(只能在节点级)搜索文档的特定值。它返回一个 True 或 False 标志来指定搜索是否成功。= 1 谓词不是次数,表示的是 True 条件,而 = 0 表示 False。
Select count(*) from invoicexml_tbl where existsNode( object_value, '/Invoice/MailAddressTo[Person="Joe Smith"]') = 1;
COUNT(*) 1
使用 XMLSequence。与 extractValue(只可从单个节点提取的值)不同,XMLSequence 可用于查看文档的多个节点或某个片段。它通过创建包含 XMLType 对象的虚拟表来完成此操作。让我们使用 MailAddressTo 分支节点来对 extractValue 和 XMLSequence 进行比较。
select extractValue(object_value, '/Invoice/MailAddressTo') from invoicexml_tbl;
from invoicexml_tbl * ERROR at line 2: ORA-19025: EXTRACTVALUE returns value of only one node
该 ORA-19025 消息具有自我说明性。幸运的是,我们可以通过重构该查询并使用 XMLSequence 解决该问题,如下所示:
select value(addr) from invoicexml_tbl i, table(XMLSequence( extract(i.object_value, '/Invoice/MailAddressTo'))) addr where existsNode(i.object_value, '/Invoice/Details[@id="2006Sept1to30PA"]') = 1;
VALUE(ADDR) <MailAddressTo id="PA"><Person>Joe Smith</Person><Street>10 Apple Tree Lane</Street><City>New York</City><State>NY</Stat e><Zipcode>12345</Zipcode></MailAddressTo>
由于 XMLSequence 创建一个虚拟表,我们也可以在叶节点上使用该函数。
select value(person) from invoicexml_tbl i, table(XMLSequence( extract(i.object_value, '/Invoice/MailAddressTo/Person'))) person where existsnode(i.object_value, '/Invoice/Details[@id="2006Sept1to30PA"]') = 1;
VALUE(PERSON) <Person>Joe Smith</Person>
FLWOR。FOR、LET、WHERE、ORDER BY 和 RETURN(FLWOR;发音为“flower”)是 XQuery 语法中最重要且最强大的表达式之一。FOR 或 LET 必须存在,WHERE 和 ORDER BY 是可选的,而 RETURN 是必需的。FLWOR 本身就是一个有待介绍的大主题。本节将为您简要介绍一下该语句的强大功能。
FOR 通过迭代方式以变量的列出顺序绑定一个或多个变量。前面列出的值之后可用在一组后续的值中。这种工作方式也类似于 SQL From 子句。前面列出的值之后可用在一组后续的值中,如下所示:
For $var in (1,2,3) , $varPlus5 in (5+$var, 5+$var, 5+$var)
这三个迭代将 $var 和 $varPlus5 分别设置为 1,6;2,7 和 3,8。
LET(类似于 FOR)以迭代方式绑定变量,可以使用以前计算的值来计算值。与使用 FOR 一样,可将 LET 看作 SQL FROM 字句。LET 也可以用于执行连接。
WHERE 过滤数据的方式与 SQL WHERE 子句相同。
ORDER BY 可以随意对数据进行排序。
RETURN 从过滤和排序后的 FLWOR 表达式返回最终结果集。
FLWOR 与 XMLQuery() 协作。以下是查询和连接两个文档的示例:用 Party 键将 partys.xml 连接到 orders.xml 文档。该 XML 数据位于 Oracle XML DB 信息库中。为此,我们将使用 XMLQuery();FLWOR;以及 XQuery 函数 doc、count、avg 和 integer。它们位于内置 XQuery 函数的命名空间中,http://www.w3.org/2003/11/xpath_functions。
以下查询读取结果如下所示:使用函数 fn:doc,对于 (FOR) partys.xml 中的所有 partyno 属性,连接 (LET) orders.xml 中匹配 partyno 的所有定单元素(变量 $p 绑定在 FOR 语句中)。这将生成一个项流($p 和 $o),其中 $p 表示一方的编号,而 $o 表示该方的一组定单。获取其中 (WHERE) 有多个定单的项。使用命名空间 fn 中的 XQuery 函数 avg 对平均数 amt 进行降序排序 (ORDER BY)。 Amt 附加到定单元素 $o。返回该方的编号(绑定到 $p)和子元素定单计数。
SELECT XMLQuery()('for $p in fn:doc("/public/partys.xml")/partys/party/@partyno let $o := fn:doc("/public/orders.xml")/orders/order[@partyno = $p] where fn:count($o) > 1 order by fn:avg($o/@amt) descending return <big-party>{$p, <ordercount>{fn:count($o)}</ordercount>, <avgamt>{xs:integer(fn:avg($o/@amt))}</avgamt>} </big-party>' RETURNING CONTENT) ORDERS FROM DUAL;
ORDERS <big-party>1111<ordercount>2</ordercount><avgamt>3500</avgamt></big-party>
是的,该查询正在进行大量工作并在 XML 文档上显示使用 FLWOR 表达式时可能出现的结果。 XQuery ora:函数
|