学习使用作为下载项包括的存储过程,对本机存储在 DB2® Viper 中的 XML 文档执行部分更新的方法。这是关于将 XML 应用程序从 DB2 UDB V8.x 迁移到 DB2 Viper 的三篇系列文章中的第一篇。
简介
DB2 Universal Database (UDB) Version 8.x 中的 XML 支持基于 DB2 的关系基础设施。在 DB2 Viper 版本之前,XML 数据要么原样存储为字符大对象 (CLOB),要么被分解到关系表中。
相反,DB2 UDB Version 9.1 具有对 XML 数据的真正本机支持。XML 现在被当作新的数据类型,XML 数据存储在经过解析的带注释的树中,独立于关系数据存储。基于 XML 模式的 XML 索引已经引入,同时还引入了对用于查询和发布 XML 数据的语言 XQuery 和 SQL/XML 的支持。为了理解这些新的 XML 特性对迁移的重大意义,需要将 DB2 8.x 中用于存储和查询 XML 数据的不同技术与 DB2 UDB Version 9 中可用的类似的或新的 XML 功能相比较。
本文是关于将 XML 应用程序从 DB2 8.x 迁移到 DB2 Viper 的三篇系列文章中的第一篇。该系列从描述一个基于 Java 的存储过程开始,您可以使用该存储过程来对 XML 数据执行子文档更新。您可以下载更新后的存储过程的源代码和 jar 文件,并根据说明安装它。
第二篇文章比较 DB2 Version 8.x 中和 DB2 Viper 中的 XML 特性。然后简要讨论 DB2 Viper 中引入的新 XML 特性,并详细介绍新 XML 支持对于迁移现有基于 XML 的应用程序的重大意义。这篇文章还包括基于 Java 的实用工具的源代码,该工具用于帮助生成迁移数据库对象时所需的脚本。
本系列的最后一篇文章介绍分步示例迁移场景。它包括示例场景的源代码。
更新存储过程
对于本机存储在 DB2 中的 XML 文档,不存在用于执行子文档更新的开箱即用的功能。缺少该功能的原因是,目前还没有定义 Xquery 中更新的标准。
该问题的一种解决方案是,将文档交给客户机,修改它,然后再将其保存到数据库中。该方法受到客户机环境的 XML 功能的限制,并且还要求专家级的人员编写基于文档对象模型 (DOM) 的客户机。
通过创建更新存储过程,可以更新数据库中的 XML 文档而无需将其交给客户机。该存储过程支持对本机存储在数据库中的 XML 文档进行部分更新。
存储过程允许:
- 更改目标 XML 文档中任何文本或属性节点的值
- 使用另一个 XML 元素替换 XML 文档中的元素节点(及其所有子节点)
- 删除 XML 文档中的节点
- 插入新元素
- 多次更新源文档
- 更新多个源文档
- 使用修改的 XML 文档替换另一个 XML 文档
- 将修改的文档插入新记录
更新信息可以:
- 静态地嵌入更新调用中
- 使用 SQL 在运行时动态地创建
- 使用算术表达式基于初始文本或属性值进行计算
注意:在后台,更新存储过程仍然执行完整的文档更新。


|
回页首 |
|
XMLUPDATE 命令
DB2XMLFUNCTIONS.XMLUPDATE (commandXML、querySQL、updateSQL、errorCode、errorMsg)

 |


|
回页首 |
|
设置存储过程
首先需要将更新存储过程 jar 安装到 DB2 中。这个过程仅需执行一次。下一步,对于每个数据库,需要分别注册存储过程。
重要事项:如果希望在存储过程中执行 Xqueries,那么需要为 DB2 设置 JCC 驱动程序。确保 DB2 在运行,然后从 DB2 命令窗口执行以下命令:
db2set DB2_USE_DB2JCCT2_JROUTINE=on
|
设置更新存储过程的步骤
- 通过执行以下步骤编译 java 代码并创建 db2xmlfunctions.jar 文件。
注意:db2xmlfunctions.jar 还可以从 下载 部分下载。如果您选择下载该文件,则跳过 第 2 步。
- 创建目录 /temp/samples。
- 将 XMLUpdate_code.zip(可以在 下载 部分找到)复制到 temp 目录。
- 将 XMLUpdate.java 和 XMLParse.java 文件解压到 /temp/samples 目录。
- 编译 java 文件并为 UDF 创建 jar 文件。
- 在 Microsoft Windows 上,打开 DB2 命令窗口:
SET CLASSPATH= .;%DB2PATH%\java\db2java.zip;
%DB2PATH%\java\db2jcc.jar;
%DB2PATH%\java\db2jcc_license_cisuz.jar;
"%DB2PATH%\java\jdk\bin\javac.exe" -d . *.java
"%DB2PATH%\java\jdk\bin\jar" cvf db2xmlfunctions.jar com/ibm/db2/xml/functions/*.class
|
在 AIX 上,将 DB2PATH 设置为 DB2 SQLLIB 目录:
CLASSPATH=$DB2PATH/java/sqlj.zip:$DB2PATH/java/db2java.zip
$DB2PATH/java/jdk/bin/javac.exe" -d . *.java
$DB2PATH/java/jdk/bin/jar" cvf
db2xmlfunctions.jar com/ibm/db2/xml/functions/*.class
|
注意:上述命令假定使用 sh 或 bash shell。根据需要更改为 csh、tsh 等。
- 在 DB2 中安装存储过程:
DB2 -t
connect to your_dbnameÿ
CALL SQLJ.INSTALL_JAR('file:/temp/samples/db2xmlfunctions.jar' ,
db2xmlfunctions,0);
|
- 在数据库中注册存储过程:
CREATE PROCEDURE db2xmlfunctions.XMLUPDATE(
IN COMMANDSQL VARCHAR(32000),
IN QUERYSQL VARCHAR(32000),
IN UPDATESQL VARCHAR(32000),
OUT errorCode INTEGER, OUT errorMsg VARCHAR(32000))
DYNAMIC RESULT SETS 0
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO DBINFO
FENCED
NULL CALL MODIFIES SQL DATA
PROGRAM TYPE SUB
EXTERNAL NAME 'db2xmlfunctions:com.ibm.db2.xml.functions.XMLUpdate.Update' ;
TERMINATE;
|
删除存储过程
如果更改了存储过程,那么在注册新版本之前应该首先从 DB2 卸载它:
DROP PROCEDURE DB2XMLFUNCTIONS.XMLUPDATE(VARCHAR(32000),
VARCHAR(32000),VARCHAR(32000),INTEGER, VARCHAR(32000));
CALL SQLJ.REMOVE_JAR(DB2XMLFUNCTIONS);
|


|
回页首 |
|
XMLUpdate 示例
对于 XMLUpdate 示例,请执行以下步骤:
- 创建测试表:
Create table XMLCustomer(cid integer not null PRIMARY KEY, info XML );
|
- 将示例 XML 文档插入表中:
Insert into XMLCustomer (cid, info ) values (1006 ,
XMLPARSE ( DOCUMENT '
<customerinfo xmlns="
http://posample.org
" Cid="1006">
<name>Hardeep Singh</name>
<addr country="United States">
<street>555 Bailey Ave</street>
<city/>
<prov-state>CA</prov-state>
<pcode-zip> 95141</pcode-zip>
</addr>
<phone type="">543-4610</phone>
</customerinfo>'
PRESERVE WHITESPACE ) );
|
注意:由于更新调用修改了初始的 XML 文档,所以您需要为某些查询而删除插入的文档,并重新插入它。
示例查询
下面是示例查询:
- 替换节点:action=replace。
通过使用复杂名称元素替换简单名称元素来更新测试文档:
Call DB2XMLFUNCTIONS.XMLUPDATE (
'<updates namespaces="x:http://posample.org">
<update action="replace" col="1" path="/x:customerinfo/x:name">
<name><fname>Hardeep</fname><lname>Singh</lname></name>
</update>
</updates>',
'Select info from XMLCustomer where cid=1006',
'update XMLCustomer set info=? where cid=1006',?,?);
|
- 使用 SQL 查询获取新值以进行更新:using=SQL。
Call DB2XMLFUNCTIONS.XMLUPDATE (
'<updates namespaces="x:http://posample.org">
<update using="sql" action="replace" col="1"
path="//x:customerinfo[@Cid=1006]/x:addr/x:pcode-zip/text()">
select cid from XMLCustomer where cid=1006
</update>
</updates>',
'Select info from XMLCustomer where cid=1006',
'update XMLCustomer set info=? where cid=1006',?,?);
|
- 使用给定表达式来计算值:action=compute。
Call DB2XMLFUNCTIONS.XMLUPDATE (
'<updates namespaces="x:http://posample.org">
<update action="compute" col="1"
path="/x:customerinfo/x:addr/x:pcode-zip/text()">
(20+?)*32-?
</update>
</updates>',
'Select info from XMLCustomer where cid=1006',
'update XMLCustomer set info=? ÿhere cid=1006',?,?);
|
- 对目标 XML 文档执行多个操作:
Call DB2XMLFUNCTIONS.XMLUPDATE (
'<updates namespaces="x:http://posample.org">
<update using="sql" action="replace" col="1"
path="/x:customerinfo/x:addr/x:pcode-zip/text()">
select cid from XMLCustomer where cid=1006
</update>
<update action="compute" col="1"
path="/x:customerinfo/x:addr/x:pcode-zip/text()">
(2+?)*10-?
</update>
<update action="delete" col="1" path="/x:customerinfo/x:name"/>
</updates>',
'Select info from XMLCustomer where cid=1006',
'update XMLCustomer set info=? where cid=1006',?,?);
|
- 更新文档时对其进行验证。
为此,您需要创建模式并在 XSR 中注册。
Call DB2XMLFUNCTIONS.XMLUPDATE (
'<updates namespaces="x:http://posample.org">
<update using="sql" action="replace" col="1"
path="/x:customerinfo/x:addr/x:pcode-zip/text()">
select cid from XMLCustomer where cid=1006
</update>
</updates>',
'Select info from XMLCustomer where cid=1006',
'update XMLCustomer set info=xmlvalidate(
? according to XMLSCHEMA ID test.schema2) where cid=1006',?,?)
|
- 使用 XMLUpdate 替换属性值。
Call DB2XMLFUNCTIONS.XMLUPDATE (
'<updates namespaces="x:http://posample.org">
<update action="replace" col="1"
path="/x:customerinfo/x:phone/@type">
tie line
</update>
</updates>',
'Select info from XMLCustomer where cid=1006',
'update XMLCustomer set info=? where cid=1006',?,?);
|
- 使用 XMLUpdate 替换文本值。
Call DB2XMLFUNCTIONS.XMLUPDATE (
'<updates namespaces="x:http://posample.org">
<update action="replace" col="1"
path="/x:customerinfo/x:addr/x:city/text()">
San Jose
</update>
</updates>',
'Select info from XMLCustomer where cid=1006',
'update XMLCustomer set info=? where cid=1006',?,?);
|
重要事项:必须在路径的末尾指定 text()。这一步确保即使是空元素(即不具有现有文本节点的元素)也进行更新。如果省略了 text() 且不存在要替换的现有文本值,更新命令就会失败。
- 使用 XMLUpdate 追加子节点。
Call DB2XMLFUNCTIONS.XMLUPDATE (
'<updates namespaces="x:http://posample.org">
<update action="append" col="1" path="/x:customerinfo/x:addr">
<county>Santa Clara</county>
</update>
</updates>',
'Select info from XMLCustomer where cid=1006',
'update XMLCustomer set info=? where cid=1006',?,?);
|
注意:新节点 <county> 不在任何名称空间中。
- 使用 XMLUpdate 将更新的 XML 插入新行。
Call DB2XMLFUNCTIONS.XMLUPDATE (
'<updates namespaces="x:http://posample.org">
<update action="replace" col="1"
path="/x:customerinfo/x:name">
<name>Marja Soininen</name>
</update>
<update action="replace" col="1"
path="/x:customerinfo/@Cid">1008</update>
</updates>',
'Select info from XMLCustomer where cid=1006',
'insert into XMLCustomer (cid, info ) values (1008, cast( ? as xml))',?,?);
|
- 使用 XMLUpdate 删除节点。
Call DB2XMLFUNCTIONS.XMLUPDATE (
'<updates namespaces="x:http://posample.org">
<update action="delete" col="1" path="/x:customerinfo/x:name"/>
</updates>',
'Select info from XMLCustomer where cid=1006',
'update XMLCustomer set info=? where cid=1006',?,?);
|
- 当更新元素中没有设置 @action 时,就默认执行替换操作。
Call DB2XMLFUNCTIONS.XMLUPDATE (
'<updates namespaces="x:http://posample.org">
<update col="1" path="//x:customerinfo[@Cid=1006]/x:phone">
<phone><areacode>910</areacode></phone>
</update>
</updates>',
'Select info from XMLCustomer where cid=1006',
'update XMLCustomer set info=? where cid=1006',?,?);
|
- 以下示例展示带有无效名称空间或带有没有前缀的名称空间的 XMLUpdate:
Call DB2XMLFUNCTIONS.XMLUPDATE (
'<updates namespaces="x:http://my.org">
<update col="1"
path="//x:customerinfo[@Cid=1006]/x:phone">
<phone><areacode>910</areacode></phone>
</update>
</updates>',
'Select info from XMLCustomer where cid=1006',
'update XMLCustomer set info=? where cid=1006',?,?);
|
该查询返回设置为 1 的错误,以及如下错误消息:
<error type='abort' action='replace' msg='Cannot find path //x:customerinfo[@Cid=1006]/x:phone) in the XMLDocument'>
- 以下示例展示的 XMLUpdate 在更新元素中有一个遗漏的路径:
Call DB2XMLFUNCTIONS.XMLUPDATE (
'<updates > <update col="1"> (20+?)*32-? </update></updates>',
'Select info from XMLCustomer where cid=1006',
'update XMLCustomer set info=? where cid=1006',?,?);
|
该查询返回设置为 1 的错误,以及如下错误消息:
<error type='abort' action='null' msg='path not defined'></error>
- 使用相同名称空间中的新节点替换某个节点。
Call DB2XMLFUNCTIONS.XMLUPDATE (
'<updates namespaces="x:http://posample.org">
<update action="replace" col="1" path="/x:customerinfo/x:name">
<name xmlns="http://posample.org">
<fname>Marja</fname><lname>Soininen</lname>
</name>
</update>
</updates>',
'Select info from XMLCustomer where cid=1008',
'insert into XMLCustomer (cid, info ) values (1007, cast( ? as xml))',?,?);
|

 |


|
回页首 |
|
结束语
本文描述的更新存储过程允许对本机存储在数据库中的 XML 文档进行部分更新。下一篇文章将深度挖掘和具体研究新的 XML 支持对迁移现有基于 XML 的应用程序的重大意义。
致谢
感谢 Matthias Nicola、Bert Van der Linden、Irina Kogan、Annie Wang、Ying Chen 和 Xiaoli Du 在撰写这篇文章时给予的帮助。


|
回页首 |
|
下载
| 描述 | 名字 | 大小 | 下载方法 |
| Update stored procedure classes |
db2xmlfunctions.jar |
13 KB |
HTTP |
| Update stored procedure source code |
XMLUpdate_code.zip |
9 KB |
HTTP |
|