XML 数据通常用于现在的生产系统,是数据库实现的主要部分。过去,这一事实给数据库开发人员带来了设计问题,使得他们必须存储、查询和更新诸如非结构化 LOB 的 XML 数据,或者将数据“分解”到关系表中,然后再将其重新组合。
命名空间中有什么?
这是一个大主题,也是需要了解的较复杂的 XML DB 概念之一。在本文中,我们将介绍一些命名空间概念,以便您了解其要旨所在及其用法。
命名空间用于描述 XML 文档中的一组相关属性或元素。命名空间可用于确保文档构造有完全唯一的名称。XMLSchema 尤其要利用该特性,因为目标命名空间通常与 XMLSchema 的 URI 相同。命名空间示例如下所示。请注意,该命名看起来类似于一个 Internet URL。该命名标准由万维网联盟 (W3C) 建议,但并非必需。该 URI 用于唯一标识数据库中注册的 XMLSchema 的名称,而且无需是文档所处位置的物理 URL。
XMLType 方法和 XML 函数使用命名空间前缀。当 XML 文档没有目标命名空间时,该命名空间前缀将位于 noNameSpace 命名空间中。属性 xsi:noNamespaceSchemaLocation 可用于模式 URI。
如果元素不具备另一个命名空间前缀,默认情况下,在将某个命名空间应用到描述它的元素时,可使用该命名空间。
通常您将看到两个特定的命名空间。它们是 http://www.w3.org/2001/XMLSchema(完整的 XMLSchema 命名空间)和 http://xmlns.oracle.com/xdb(Oracle 提供的 XML DB 命名空间)。第二个命名空间具有写入基础 SQL 函数的函数。一些 XPath 函数
也进行重写。例如 ora:contains、ceiling、floor、not、string-length、substring 和 translate。XML DB 使用的属性也属于该命名空间。
定义元素时,我们可以指定该元素的命名空间。在 XML 中,我们可以将它定义为
如您所见,我们提供了一个 elementName,它是我们将使用的元素(例如,“orders”)。Xmlns 是保留字,它告诉我们这是一个命名空间定义。“ab”部分称为前缀。该前缀是一个绑定到 URL 的简称。在本例中,ab 绑定到‘http.name.com’,而且 ab 可以加为元素名的前缀。
下面我们将创建一个非常小的模式,并声明绑定前缀 xs 到 http://www.w3.org/2001/XMLSchema
以
及
声
明
前
缀
xdb
到
http://xmlns.oracle.com/xdb。为了声明该命名空间,我们使用 xmlns 绑定它们。请注意,xs 前缀在本例中用在模式元素名称上。
name=\"INVOICESCHEMA\"
这里我们只是粗略介绍了一下命名空间。有关该主题的更多信息,请参阅 Oracle 技术网 (OTN) 上的 Oracle XML DB 开发人员指南 10g 第 2 版。
使用 XML
将数据添加到 XMLType 表和列中。正如您可能预期到的,有很多选项可供我们将 XML 数据添加到数据库中。可以使用 SQL、PL/SQL、Java 和 C 程序插入数据。也可以使用 XMLType 表的 SQL*Loader 和 Import/Export 函数将数据加载到数据库中。可以使用 Oracle Streams 来移动 XML 数据,还可以使用 DBMS_XDB 函数。现在,就让我们来探究一个简单易用的方式来加载 XML 数据。
在本例中,我们将使用 SQL 插入将一个 XML 文档从文件加载到表中,以便从 bfile 加载该 XML 文档。该文件需要通过一个数据库目录访问。为此,我们将创建一个目录以指向存储该 XML 文档文件的文件。请注意,要执行本文中的示例,您必须确保所用用户具有 xdbadmin 角色。
create or replace directory xmldir as ’/u01/app/oracle/admin/db01/sql’;
现在我们可以用两种方式创建包含 XMLType 数据的表。第一个将是具有 XMLType 列的表。第二个将是定义为类型 XMLType 的表。
1.创建一个包含 XML 列的表。
create table invoiceXML_col (
inv_id number primary key,
inv_doc XMLType);
2.创建一个 XML 表。
create table invoiceXML_tbl of XMLtype;
以上每一个语句都在每个表中隐式创建两个索引 — 一个用于主键,另一个用于 LOB。
现在我们要将一个文档插入到这两个表中。请注意,我们要使用字符集 AL32UTF8,并指定它传送字符集编码来供要读取的文件使用。数据将插入这两个表以显示这两个 SQL 语句间的相似性。
Insert into invoicexml_col values (1,
XMLType(bfilename(’XMLDIR’, ’invoicexml.txt’),
nls_charset_id(’AL32UTF8’) ));
Insert into invoicexml_tbl values
(XMLType(bfilename(’XMLDIR’, ’invoicexml.txt’),
nls_charset_id(’AL32UTF8’)));
我们现在已经使用 XMLType 表和列将两个 XML 文档加载到了数据库中。就是这么简单。
注册和实现模式类型化数据
如果处理命名空间和存储技术不足,XMLType 数据也可以实现为模式类型化或非类型化数据。XMLSchema 可将文档与提供文档结构和内容信息的 XMLSchema 相关联。这为文档提供了更好的记录、验证和控制。该模式中的信息可用于提交更有效的查询和更新处理。XMLSchema 也允许将 XML 文档存储为结构化存储数据,因为该文档可以通过 XMLSchema 分解为一组对象。用于存储该文档的对象模型由模式定义确定。XMLType 方法 schemaValidate() 和 isSchemaValid() 允许使用模式定义编辑 XMLType 文档。
我们如何创建模式并在 XML 文档中使用它?为此,我们需要创建一个 XMLSchema 定义
注册该模式
创建一个基于 XMLSchema 的表
将数据插入其中
下面的示例分四步进行了说明。
1.首先,在目录 XML_DIR 下的文件 invoiceformtest.xsd 中创建一个模式定义。该清单如下所示:
name=\"INVOICEFORMTEST\"
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:defaultTable=\"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
完成!
了解 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
使用 extract。使用 extract 时,通过将 extract 与 object_value 合并,可从文档选择单个节点及其叶节点。换言之,我们可以查看存储为 XMLType 的 XML 文档。无论我们使用的是结构化数据还是非结构化数据以及数据是否基于模式,情况都是如此。开始提取 MailAddressTo 节点及其叶节点。
select extract(object_value, ’/Invoice/MailAddressTo’) from invoicexml_tbl;
EXTRACT(OBJECT_VALUE,’/INVOICE/MAILADDRESSTO’)
Apple Tree Lane
如您所见,该输出包括文档的 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)
Apple Tree Lane
由于 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)
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
RETURNING CONTENT) ORDERS FROM DUAL;
ORDERS
是的,该查询正在进行大量工作并在 XML 文档上显示使用 FLWOR 表达式时可能出现的结果。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- baijiahaobaidu.com 版权所有 湘ICP备2023023988号-9
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务