IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Information Management | XML  >

DB2 V9.5 中针对 XML 数据完整性和验证的新选项

通过触发器支持 CHECK 限制进行验证

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

讨论

英文原文

英文原文


级别: 中级

Manoj Sardana, 资深软件工程师, IBM
Madhavi Kaza, 软件工程师, IBM

2009 年 11 月 05 日

IBM® DB2® for Linux®, UNIX®, and Windows® 在版本 9 中引入了 pureXML® 技术。该技术允许您以原生格式存储 XML 数据,从而维护 XML 的层次结构并允许您使用 SQL/XML 和 XQuery 查询它们。就像关系数据一样,必须确保储存在 DB2 中的 XML 数据的完整性。不过,确保 XML 数据的完整性的方法和机制与保持传统的关系数据的完整性有所不同。在本文中,您将了解 DB2 环境中的 XML 数据的完整性,并探索在各种场景中保证完整性的不同选项。

XML 完整性

在 DB2 数据库中,可以从多个角度考察 XML 数据的完整性。在最基础的级别上,在将 XML 值插入到表中之前,您可能希望各种元素值的数据类型是正确的。在更高级别上,您可能希望使用限制,比如元素值的唯一性和某个元素的多样性,或限制元素的值。当使用关系数据的形式储存 XML 数据时,您可能希望确保 XML 中的一部分元素值也存在关系列中,这是因为这些列可能是主键或外键的一部分。

DB2 为这些完整性需求提供许多不同的解决方案。尽管您可以选择在插入之前根据模式验证 XML 文档,但是还可以使用触发器自动完成验证,而不需要用户参与。您可以使用检查(CHECK)限制强制用户使用预注册的模式验证 XML 值。在您使用这些选项之前,必须在数据库中注册 XML 模式。要在关系列中储存节点值以维护唯一性,您可以使用 SQL/XML 函数将适当的节点值分割为关系数据类型,然后将其储存到关系列中。在下面的小节中,我们将通过代码样例详细讨论这些选项。





回页首


XML 模式注册和验证

XML 模式用于定义 XML 文档的结构、元素、属性以及元素和属性的数据类型。另外,它允许您指定元素的默认值和限制(比如多样性和唯一性)。定义了 XML 模式之后,就可以根据指定的 XML 模式验证 XML 文档。清单 1 显示了一个 “employee” 示例模式。我们将在本文的后面部分使用该模式。


清单 1. Employee 模式
				
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
		elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name = "employee">
    <xs:complexType>
        <xs:sequence>
            <xs:element name = "name" type = "xs:string"/>
            <xs:element name = "dept" type = "xs:string"/>
            <xs:element name = "salary" type = "xs:double"/>
            <xs:element name = "designation" type = "xs:string"/>
            <xs:element name = "date-of-join" type = "xs:date"/>
            <xs:element name = "address">
                 <xs:complexType>
                     <xs:sequence>
                            <xs:element name = "street" type = "xs:string"/>
                            <xs:element name = "city" type = "xs:string"/>
                            <xs:element name = "state" type = "xs:string"/>
                            <xs:element name = "country" type = "xs:string"/>
                            <xs:element name = "zipcode" type = "xs:string"/>
                     </xs:sequence>
                 </xs:complexType>
           </xs:element>
         </xs:sequence>
         <xs:attribute name = "id" type = "xs:string" use = "required"/>
      </xs:complexType>
   </xs:element>
</xs:schema>
		

在使用 XML 模式进行验证之前,必须在 DB2 数据库中注册它。清单 2 显示了注册 employee 模式的 CLP 命令,假设它储存在您使用的目录的 employee.xsd 文件中。


清单 2. 注册 XML 模式
				
REGISTER XMLSCHEMA http://posample.org FROM employee.xsd as employee;
COMPLETE XMLSCHEMA employee; 
			

模式注册成功并获得一个关系名之后,您就可以用它进行验证了。

验证就是检查实例文档是否满足在 XML 模式中指定的结构、数据类型和内容限制的过程。验证在将数据插入到数据库之前排除了无效数据。它确保 XML 文档遵循 XML 模式提供的规则,从而保持良好的构造。

在 DB2 中,根据 XML 模式验证 XML 文档是可选的。例如,如果从可信源获取 XML 文档的话,就不需要进行验证。相反,如果从未知源获取 XML 文档,则要验证 XML 文档以维护数据的完整性。

在将 XML 文档插入到表中或更新表中的 XML 文档时,使用 XMLVALIDATE 函数验证它。如前所述,在使用 XML 模式进行验证之前必须先注册它。

XMLVALIDATE 可以显式或隐式地验证文档。

  • 隐式验证:XML 文档使用 xsi:schemaLocation 属性指定模式位置和名称空间,或使用 xsi:noNamespaceSchemaLocation 属性仅指定模式的位置。DB2 接受这些输入值并搜索目录表以识别验证 XML 文档所需的 XML 模式。例如,您可以将以下 XML 文档插入到拥有两个列的现有 EMPLOYEE 表中,第一个类型为 integer,第二个列类型为 XML。


    清单 3. 隐式验证
    						
    INSERT INTO employee VALUES (101, 
    '<employee xmlns:xsi="http://www/w3.org/2001/XMLSchema" 
    			xsi:noNamespaceSchemaLocation="employee.xsd" id = "101">
    	<name>Sonal</name>
    	<dept>Sales</dept>
    	<salary>10000</salary>
    	<designation>Sales Executive</designation>
    	<date-of-join>2007-10-10</date-of-join>
    	<address>
      		<street>M.G. Road</street>
      		<city>Bangalore</city>
      		<state>Karnataka</state>
      		<country>India</country>
      		<zipcode>560001</zipcode>
    	</address>
    </employee>')
    			

  • 显式验证:XML 文档在 XMLVALIDATE 函数中使用 ACCODING TO XMLSCHEMA ID 子句显式地指定 SQL 标识符或名称空间,以及 XML 模式的模式位置信息。下面的例子显示了显式验证。


    清单 4. 显式验证
    						
    INSERT INTO employee VALUES (101, XMLVALIDATE(XMLPARSE(document 
             '<employee id="101">
                <name>Sonal</name>
                <dept>Sales</dept>
                <salary>10000</salary>
                <designation>Sales Executive</designation>
                <date-of-join>2007-10-10</date-of-join>
                <address>
                    <street>M.G. Road</street> 
                    <city>Bangalore</city>
                    <state>Karnataka</state>
                    <country>India</country>
                    <zipcode>560001</zipcode>
                </address>
             </employee>') ACCORDING TO XMLSCHEMA ID employee))
    			

在 DB2 中,XML 文档验证是以每个文档为单位进行验证的,而不是以列为单位进行验证。对于包含 XML 列的表,不一定要将所有文档关联到一个 XML 模式。XML 文档可以关联到不同的 XML 模式。您可以使用 VALIDATED 谓词检查是否验证了文档。





回页首


通过 XML 文档上的 CHECK 限制进行验证

考虑这样一个场景,您需要将一组 XML 模式绑定到一个 XML 列。不过,验证 XML 值是由应用程序负责的。对于这种情况,DBA 可以在 XML 列上放置检查(check)限制,并确保应用程序使用预注册的模式之一执行验证。这确保 XML 文档经常得到验证。

检查限制是表的列上的限制,用于将用户限制到特定的检查条件。在列上执行插入或更新操作时,仅当检查条件的结果计算为真时才能执行这两项操作。

创建一个 XML 列包含检查限制的表

XML 上的检查限制使您能够根据 XML 模式验证在 XML 列上指定限制,从而确保仅将使用正确模式验证的 XML 文档储存在列中。此外,它还使您能够在根据一组预定义的模式验证 XML 文档时给 XML 值定义 XML 表达式。可以使用带有 ACCORDING TO XMLSCHEMA 子句的 IS VALIDATED 或 IS NOT VALIDATED 谓词确定是否根据指定的模式验证了 XML 文档。

检查限制还可以列出一组模式。这意味着可以根据指定的 XML 模式之一验证 XML 文档。通过在检查限制中提供多个模式,您可以灵活地选择一个模式用于验证,从而帮助将多个模式与特定 XML 列关联起来。清单 5 中的例子显示了如何在检查限制中指定一个模式。


清单 5.在 XML 列上创建检查限制
				
CREATE TABLE customer (cust_id INTEGER NOT NULL, 
      info XML CONSTRAINT val_check 
      CHECK(info IS VALIDATED ACCORDING TO XMLSCHEMA ID customer))
			

以上例子在类型为 XML 的 INFO 列上创建了一个检查限制。该检查限制确保根据 customer 模式验证文档(假设在 DB2 中注册了 customer 模式)。注意,检查限制计算是否验证了 XML 文档,它并不执行实际的验证。

清单 6 中的例子显示了如何在创建一个特定的检查限制时列出多个模式。


清单 6. 在 XML 列上创建包含多个模式的检查限制
				
CREATE TABLE customer (cust_id INTEGER NOT NULL,
          cust_info XML CONSTRAINT val_check 
          CHECK (cust_info IS VALIDATED ACCORDING TO XMLSCHEMA IN 
          (ID registered_customers, ID online_customers, ID regular_customers)))
          

以下例子中的插入语句将失败,因为它根据没有在检查限制子句中指定的模式验证 XML 文档。


清单 7. 检查限制违背
				
INSERT INTO customer 
VALUES (1001, XMLVALIDATE(XMLPARSE(cust_info) 
ACCORDING TO XMLSCHEMA ID cust))
			

通过视图插入 XML 值

您还可以通过视图将 XML 文档插入到各自基表中。当通过视图在 XML 列上执行插入操作时,将在 XML 文档上应用该基表的检查限制,并且仅当 XML 文档满足检查限制时,它才能插入到表中。下面的例子在两个包含 XML 文档的表上创建视图。


清单 8. 通过视图插入 XML 文档
				
CREATE TABLE distributor (dist_id INTEGER, dist_info XML 
	CONSTRAINT dist_check 
	CHECK(dist_info IS VALIDATED ACCORDING TO XMLSCHEMA ID distributor))
		
CREATE VIEW cust_dist_view(id, details) AS 
(SELECT id, info FROM customer 
UNION ALL
SELECT dist_id, dist_info FROM distributor)

INSERT INTO cust_dist_view VALUES (id, XMLVALIDATE(XMLPARSE(details)
ACCORDING TO XMLSCHEMA ID distributor))

INSERT INTO cust_dist_view VALUES (id, XMLVALIDATE(XMLPARSE(details) 
ACCORDING TO XMLSCHEMA ID registered_customers))
			

CREATE VIEW 语句创建了 CUSTOMER 和 DISTRIBUTOR 表的视图。如果储存在 DETAILS 中的 XML 数据根据 XML 模式 DISTRIBUTOR 进行验证时,第一个插入语句将把数据插入到 DISTRIBUTOR 表。如果储存在 DETAILS 中的 XML 数据根据 XML 模式 REGISTERED_CUSTOMERS 进行验证时,第二个插入语句将把数据插入到 CUSTOMER 表。

依赖 XML 模式的检查限制和视图

在 XML 列包含检查限制的表上构建的检查限制和视图依赖于 XML 模式。如果删除 XML 模式,那么检查限制将无法根据已删除的模式检查验证,从而导致插入成功。


清单 9. 依赖 XML 模式的检查限制和视图
				
DROP XSROBJECT customer
DROP VIEW cust_dist_view
INSERT INTO customer VALUES(201, cust_info)
INSERT INTO cust_dist_view VALUES (202, details);

			

CUSTOMER 表和 CUST_DIST_VIEW 上的插入操作不通过任何验证,并且最终成功。





回页首


通过触发器强制执行自动验证

如果应用程序很难更改插入语句来执行显式验证,那么 DBA 可以编写一个触发器,它将在每次插入或更新操作发生时触发,以自动执行验证。

DB2 9.5 引入了使用 BEFORE 触发器对进入的 XML 文档强制执行自动验证 的概念。当在表上执行插入或更新操作时,自动验证确保根据指定的 XML 模式对 XML 文档进行验证。自动验证是由触发器语句的操作部分通过 XMLVALIDATE 函数完成的。

创建强制执行自动验证的 BEFORE 触发器语句

当在表上插入或更新 XML 文档时,将执行触发器。触发器语句的操作部分包含 XMLVALIDATE 函数,它根据指定的模式验证 XML 文档。

例如,employee 表包含雇员 ID 和雇员信息。雇员 ID 列 EMP_ID 的类型为 integer,雇员信息列 INFO 的类型为 XML。INFO 列包含雇员信息,比如在 XML 文档中列出的姓名、职责、薪水、入职日期、部门和联系方式。可以通过以下方式对进入的 XML 文档执行自动验证。


清单 10. 使用 BEFORE 触发器语句验证雇员信息
				
CREATE TABLE employee (emp_id INTEGER, info XML);                                

CREATE TRIGGER val_trig NO CASCADE BEFORE INSERT on employee
REFERENCING NEW AS n
FOR EACH ROW MODE DB2 SQL 
BEGIN ATOMIC
set (n.info) = XMLVALIDATE (n.info ACCORDING TO XMLSCHEMA ID employee);
END
			

触发器语句的操作部分的 XMLVALIDATE 函数验证在 INFO 列中指定的雇员信息。ACCORDING TO XMLSCHEMA 子句用于根据 XML 模式验证 INFO。当将 XML 文档插入到 EMPLOYEE 表时,将执行 BEFORE INSERT 触发器语句,并根据 employee 模式验证 XML 文档。仅当验证成功时,记录才能插入到表中。

注意:如果触发器验证 XML 文档失败,那么就不能插入该文档,同时也不返回任何错误消息。

在 WHEN 子句中使用 IS {NOT} VALIDATED 谓词

应用程序经常在插入 XML 文档之前验证它。不过,同时还可能定义了执行自动验证的触发器。对于这种情况,重复验证 XML 文档将导致增加额外的开销。

对于这种情况,可以将触发器实现为先确定是否执行了验证。如果已经执行了验证,那么在触发器代码体中使用 WHEN 子句跳过验证过程。仅当 WHEN 子句的计算结果为真时,触发器语句的操作部分才会执行。下面的例子演示了在触发器中使用 WHEN 子句。


清单 11. 在 BEFORE UPDATE 触发器语句中使用 WHEN 子句
				
CREATE TRIGGER val_trig NO CASCADE BEFORE UPDATE ON employee
REFERENCING NEW AS n
FOR EACH ROW MODE DB2 SQL
WHEN (n.info IS NOT VALIDATED ACCORDING TO XMLSCHEMA ID employee)
BEGIN ATOMIC
set (n.info) = XMLVALIDATE(n.info ACCORDING TO XMLSCHEMA ID employee);
END
			

如果已经根据指定的模式验证了文档,IS VALIDATED 谓词将返回 true,否则返回错误。如果没有根据指定的模式验证 XML 文档,IS NOT VALIDATED 谓词返回 true。如果 XML 文档已经被验证,将返回 false。因此,如果已经验证了文档,将不再执行验证。如果还没有验证文档,将执行触发器语句的操作部分,并根据指定的模式验证 XML 文档。

在清单 11 的代码中,WHEN 子句检查确定 XML 文档 INFO 是否根据 EMPLOYEE 模式进行了验证。如果结果为真,那么将在触发器语句中根据 EMPLOYEE 模式验证 INFO 文档。否则,将不执行触发器语句的操作部分。

根据位于特定 URI 的模式验证 XML 文档

我们可以根据位于特定 URI 的模式验证 XML 文档。可以使用 ACCORDING TO XMLSCHEMA 子句根据在 XMLVALIDATE 函数中指定的 URI 验证 XML 文档 INFO。清单 12 显示了一个例子。


清单 12. 根据指定的 URI 验证雇员信息
				
CREATE TRIGGER val_trig NO CASCADE BEFORE INSERT ON employee 
REFERENCING NEW as n
FOR EACH ROW MODE DB2SQL 
BEGIN ATOMIC 
  set n.info = XMLVALIDATE(n.info ACCORDING TO XMLSCHEMA URI 
                     'http://posample1.org');  
END
			

XMLVALIDATE 函数根据在 URI http://posample1.org 上指定的模式验证雇员信息。

在过渡变量上限制 XML 函数

DB2 9.5 BEFORE 触发器限制在过渡变量(transition variables)上使用函数。如果您在过渡变量上使用 XMLVALIDATE 之外的其他任意 XML 函数,触发器的创建将失败。例如:


清单 13. 在过渡变量上使用 XMLELEMENT 函数
				
CREATE TRIGGER val_trig NO CASCADE BEFORE INSERT ON employee
REFERENCING NEW AS n 
FOR EACH ROW MODE DB2SQL 
BEGIN ATOMIC
set (n.id) = 1000;
set (n.info) = XMLDOCUMENT(XMLELEMENT(name Russel, n.info));
END
			

这个 CREATE TRIGGER 语句将失败,因为触发器的操作部分在过渡变量 n.info 上使用了 XMLELEMENT 函数。





回页首


在 SELECT 中使用 IS VALIDATED 和 IS NOT VALIDATED 谓词

在 DB2 中验证是可选的。表可以在它的一个列中同时储存经过验证和未经过验证的 XML 文档。如果已经根据特定的模式或任何已注册模式验证了 XML 文档,IS VALIDATED 谓词将返回 true,否则返回 false。如果还没有根据特定的模式或任何已注册模式验证了 XML 文档,IS NOT VALIDATED 谓词将返回 true,否则返回 false。这些谓词还可以用于 SELECT 语句的 WHERE 子句中。


清单 14. 使用 IS VALIDATED 谓词
				
SELECT cust_id, cust_info FROM customer 
WHERE cust_info IS VALIDATED
			

这个语句仅从 CUSTOMER 表获取根据已注册模式验证的 CUST_INFO 文档。您可以使用 ACCORDING TO 子句仅获取已根据指定的模式验证的 XML 文档,如清单 15 所示:


清单 15. 使用带有 ACCORDING TO 子句的 IS VALIDATED 谓词
				
SELECT cust_id, cust_info FROM customer
WHERE cust_info IS VALIDATED ACCORDING TO XMLSCHEMA ID registered_customers
			

这个语句仅从 CUSTOMER 表获取根据 REGISTERED_CUSTOMERS 模式验证的 CUST_INFO XML 文档。


清单 16. 使用 IS NOT VALIDATED 谓词
				
SELECT cust_id, cust_info FROM customer
WHERE info IS NOT VALIDATED 
			

这个语句将从 CUSTOMER 表获取每个根据已注册 XML 模式进行验证的 CUST_INFO 文档。我们将 ACCORDING TO 子句与 IS NOT VALIDATED 谓词一起使用,如清单 17 所示:


清单 17. 结合使用 ACCORDING TO 子句和 IS NOT VALIDATED 谓词
				
SELECT cust_id, cust_info FROM customer
WHERE info IS NOT VALIDATED ACCORDING TO XMLSCHEMA ID registered_customers
			

这个语句将从 CUSTOMER 表获取所有未根据 REGISTERED_CUSTOMERS 模式进行验证的 CUST_INFO XML 文档。





回页首


将 XML 值分开储存到关系列中

不能对 XML 文档的特定值执行限制,比如主键—外键关系和值的唯一性。不过,如果 XML 文档要求使用特定的元素,那么可以将该元素的值分开储存在一个关系列中,然后相应地应用限制。清单 18 中的代码通过分割 EMPLOYEE 表的 INFO XML 列的值,以从 EMPLOYEE 表选择值并将其插入到临时表中。


清单 18. 使用 SQL/XML 将 XML 元素值分割到关系列中
				
INSERT INTO TEMP (SELECT id,info FROM 
     employee, xmltable('$INFO/employee' COLUMNS id INT PATH '@id') AS t)
			

不过,这种分割方式会创建重复数据。因此,您需要确保多个位置的数据是一致的。在这里,分割后的关系列的 ID 值应该总是与 XML 列中的值匹配。可以在该列上为 INSERT 和 UPDATE 操作创建存储过程来维护这种一致性。当用户插入 XML 值时,将通过分割从 XML 值获取数据并将其储存在关系列中。类似地,UPDATE 操作也能更新关系值。也可以使用类似的存储过程限制或执行相反的操作(更新关系列导致同时更新 XML 文档)。清单 19 显示了一个存储过程例子,它分割数据然后将正确的值插入到列中。


清单 19. INSERT 存储过程
				
    	CREATE PROCEDURE INSERTEMPLOYEE (XML INFO)
P1: BEGIN
	DECLARE P1 INTEGER;

SELECT ID INTO P1 FROM XMLTABLE('$INFO/employee' PASSING INFO AS "INFO" 
                COLUMNS ID INT PATH '@id') AS T;

INSERT INTO TEMP
  VALUES (ID, INFO);

END P1
    	





回页首


结束语

DB2 9 支持原生格式的 XML 数据,并为查询数据提供各种选项。在本文中,我们探索了许多新方法,它们确保在查询、插入、更新或删除数据时保持 XML 数据的一致性。针对 XML 的触发器支持允许使用 XMLVALIDATE 函数实现自动验证。您可以使用这些选项确保数据在其生命周期中保持一致和正确。





回页首


致谢

作者衷心感谢 Susan Malaika 和 Iti Rawat 审查了本文并提供宝贵建议。



参考资料

学习

获得产品和技术

讨论


作者简介

Manoj Sardana

Manoj Sardana 是 IBM 印度软件实验室的资深软件工程师。目前他在 pureQuery 开发团队工作。他在过去为 DB2 的新特性开发样例应用程序。他还参与 DB2 的功能性验证测试项目。他是通过 IBM 认证的应用程序开发人员和 DB2 9 高级数据库管理员。他还是 IBM 认证的 XML 和相关技术的解决方案开发人员。


Madhavi Kaza 的照片

Madhavi Kaza 为印度软件实验室的 DB2 ID 样例和技术演示团队工作。她从事 XML 特性的样例开发。她为 DB2 9 和 9.5 XML 特性开发过许多 XML 样例,现在为 DB2 9.7 开发样例应用程序。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款