SQL Server 2005数据库管理高级教程http://book.csdn.net/bookfiles/583/
8.5 XML数据类型的查询方法
Microsoft SQL Server 2000通过Microsoft SQL XML使用户可以使用XML数据类型,它允许把关系型数据转换为XML,把XML数据保存在关系型表中。Microsoft SQL Server 2005通过把XML作为一种数据类型来实现这一功能,此外,它还提供了针对XML文档的新的查询语句和定位修改。
8.5.1 XQuery
XML查询语言(通常被称为XQuery)是一种专门查询各类XML数据的高效智能语言。使用XQuery,可以对XML数据类型字段和变量进行查询。与许多XML标准一样,World Wide Web Consortium(W3C)组织一直监督着XQuery的开发工作。实际上,XQuery由Quilt查询语言发展而来,它基于多种查询语言,如XML Path Language (XPath) 1.0及2.0、XQL和SQL。因此,与XPath1.0相比,XQuery的功能得到显著地增强。
与其早期版本相比,SQL Server 2005提供了更为丰富的XQuery功能。提供了在数据层操作XML对象的途径。SQL Server 2005提供的XQuery功能支持XQuery 1.0。
本节首先介绍一些与XQuery相关的基本知识,然后进一步介绍SQL Server 2005提供的XML功能。由于XQuery不是本书介绍的主要内容,所以在此不作深入讨论。
1. XPath基本概念
XQuery提供了“路径语法”的概念,称为XPath。实际上XPath是一套语法,基于这套语法之上的表达式,即XPath表达式用于定位XML文档中的节点(无论该节点是一个元素,还是一个属性)。使用XPath可以准确地定位XML文档中的任一节点,无论是元素节点,还是属性节点。从这一点上看,XPath语法与描述操作系统中的文件路径名的规范有点相似。
与其他有关路径的概念一样,XPath也有绝对路径和相对路径之分。描述一个绝对路径时需要使用斜杠(/)。
例如,前面介绍的数据表xsc_Categories中,第一条记录的CategoryInfo字段值为:
<?xml version="1.0" encoding="gb2312"?>
<CategoryInfo xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">
<CategoryId>
1
</CategoryId>
<CategoryName>
candy
</CategoryName>
<Description>
chocolate,panocha
</Description>
</CategoryInfo>
很明显,此XML文档的根元素为CategoryInfo。如果想查看元素CategoryInfo中的所有内容可以使用XPath表达式:“/CategoryInfo”。如果想查看CategoryName中的内容,应使用XPath表达式:“/CategoryInfo/CategoryName”。看上去是否与在操作系统中查看根目录C:"和C:"Windows有些相像呢。
另一方面,在XPath中也可以使用相对路径,此时需要使用双斜杠(//),查找XML文档中所有符合“//”之后定义的表达式的节点值。例如使用“//Description”时将返回XML文档中Description元素的所有值。使用“//CategoryInfo/CategoryName”可以查找<CategoryInfo>中的<CategoryName>元素内包含的值。
XPath定义的主要语法符如表8.9所示。
表8.9 XPath定义的主要语法符
语法符 |
含 义 |
* |
表示选择所有星号之前的表达式所指定的元素 |
[ ] |
利用方块号里的表达式进一步指定具体的元素,其中数字表示元素在选择集里的位置,而last()函数则表示选择集中的最后一个元素。当存在多个同名元素或属性时,[ ]中的值就像是一个元素数组或属性数组的索引值一样被用于检索指定的元素或数组 |
@ |
用于指明XML文档中的属性 |
COUNT() |
用于计算所选元素的个数,例如//*COUNT(*)用于选择拥有两个子元素的元素 |
Name() |
返回元素的名称,常与Start-WITH、true、CONTAINS()函数配合使用。例如//*[CONTAINS(name(),'xxx')]表示查找名称中包含'xxx'的那些元素 |
表8.9只列出了XPath中的一些主要语法和主要使用方法。有关XPath的更多信息在此不做更多地介绍,感兴趣的读者可选读与之相关的资料。
2. FLWOR支持
FLWOR实际上是一组命令的简称,这些命令主要用于在编写XML查询时实现循环功能,它们分别是For命令、Let命令、Where命令、Order By命令以及Return命令。
使用FLWOR命令实现循环查询时,需要定义用于控制循环流程的控制变量,上述命令中Where和Order By命令是可选的,而Return命令是必需的。
【示例19】FLWOR语句的使用。
下面通过示例简要地介绍FLWOR语句的使用方法,步骤如下。
(1) 打开【查询编辑器】,在其中输入以下Transact-SQL脚本代码:
DECLARE @tmpXML AS XML
SET @tmpXML = '
<Categories>
<CategoryInfo CategoryID ="1">
<CategoryName>Beverages</CategoryName>
<Description>Soft drinks, coffees, teas, beers, and ales</Description>
</CategoryInfo>
<CategoryInfo CategoryID ="2">
<CategoryName>Condiments</CategoryName>
<Description>Sweet and savory sauces, relishes, spreads, and seasonings</Description>
</CategoryInfo>
<CategoryInfo CategoryID ="3">
<CategoryName>Confections</CategoryName>
<Description>Desserts, candies, and sweet breads</Description>
</CategoryInfo>
<CategoryInfo CategoryID ="4">
<CategoryName>Dairy Products</CategoryName>
<Description>Cheeses</Description>
</CategoryInfo>
</Categories>
'
SELECT @tmpXML.query('
FOR $var IN /Categories/CategoryInfo
RETURN ($var)') AS test
GO
(2) 上述Transact-SQL脚本中使用了XML数据类型的query()方法,该方法的相关内容将在随后的小节中进行介绍。脚本接下来使用FLWOR查询XML类型变量@tmpXML中节点/Categories/CategoryInfo的值。单击【执行】按钮,运行上述Transact-SQL脚本,其结果如图8.34所示。
(3) 如果想查询CategoryID为2的元素,可以在上述Transact-SQL脚本中添加一条Where从句,如下所示:
SELECT @tmpXML.query('
FOR $var IN /Categories/CategoryInfo
WHERE $var /@CategoryID ="2"
RETURN ($var)') AS test
GO
图8.34 查询结果
(4) 上述脚本代码中使用@CategoryID="2"作为查询条件。单击【执行】按钮,其结果如图8.35所示。
图8.35 查询结果
提示 |
|
Xquery语法要求大小写敏感,所以无论查询的是关键字还是XPath表达式,都需要注意大小写。例如,如果将上述代码中的/Categories/CategoryInfo更改为/categories/CategoryInfo,查询结果将为空集。除此之外,还要注意的是,SQL Server 2005中的XQuery查询不支持FLWOR中的L(即let)命令。 |
3. XQuery函数
SQL Server 2005对XQuery提供的大量函数提供了支持,其中包括聚合类函数、数据访问函数、数值函数,字符串函数以及上下文函数等类型。经常被使用的函数如表8.10所示。
表8.10 常用函数
类 别 |
说 明 |
聚合类函数 |
完成各类统计功能,其中包括COUNT(计算)、AVG(求平均值)、MIN(最小值)、MAX(最大值)和SUM(求和)等函数 |
数据访问函数 |
其中包括string,即返回一个代表XML节点的字符串和data,返回指定节点的值 |
续表
类 别 |
说 明 |
数值函数 |
包括CEILING(返回比指定值大的最小值)、FLOOR(返回比一个指定值小的最大值)、ROUND(返回最接近指定值的整数) |
字符串函数 |
完成字符串处理的函数,例如CONCAT(字符串连接函数)、CONTAINS(判断是否包含指定的子字符串)、SUBSTRINT(获取子字符串)以及STRING-LENGTH(获取指定字符串的长度) |
上下文函数 |
LAST(返回当前序列中被处理的项目数)、POSITION(返回指定项目在序列中的位置) |
除表8.10中介绍的主要函数之外,SQL Server 2005还对其他大部分XQuery函数提供了支持。下面通过一些示例进行简要地介绍。
【示例20】对示例19进行改造。
完整的设计过程如下。
(1) 将上面的Transact-SQL脚本的后半段改造如下:
SELECT @tmpXML.query('
FOR $var IN /Categories/CategoryInfo
WHERE (data($var /@CategoryID)) GT 2
RETURN ($var)
') AS test
GO
(2) 上述代码中,使用了XQuery函数的data函数来获取属性CategoryID的值,因此可以执行数值比较操作。单击【执行】按钮,运行上述Transact-SQL脚本,其结果如下所示:
<CategoryInfo CategoryID="3">
<CategoryName>Confections</CategoryName>
<Description>Desserts, candies, and sweet breads</Description>
</CategoryInfo>
<CategoryInfo CategoryID="4">
<CategoryName>Dairy Products</CategoryName>
<Description>Cheeses</Description>
</CategoryInfo>
(3) 继续将上述Transact-SQL脚本改造为下面的形式:
SELECT @tmpXML.query('
FOR $var IN /Categories/CategoryInfo
WHERE (data($var /@CategoryID)) GT 2
RETURN
ELEMENT CategoryInfo
{
ATTRIBUTE CategoryID {string($var/@CategoryID[1])},
ELEMENT CategoryName {string($var/CategoryName[1])},
ELEMENT Description {string($var/Description[1])}
}
') AS test
GO
(4) 其中使用了数值型函数string来返回指定节点的字符串值。单击【执行】按钮,其结果如图8.36所示。
图8.36 查询结果
(5) 将上述Transact-SQL脚本改造如下:
SELECT @tmpXML.query('
FOR $var IN /Categories/CategoryInfo
WHERE $var/@CategoryID =MIN(Categories/CategoryInfo/@CategoryID)
RETURN
ELEMENT CategoryInfo
{
ATTRIBUTE CategoryID {string($var/@CategoryID[1])},
ELEMENT CategoryName {string($var/CategoryName[1])},
ELEMENT Description {string($var/Description[1])}
}
') AS CategoryInfo
GO
(6) 上述Transact-SQL脚本代码中使用min函数获取属性CategoryID值最小的那个元素。单击【执行】按钮,其结果如图8.37所示。
图8.37 查询结果
(7) 继续对上面的Transact-SQL脚本进行修改,在【查询编辑器】中输入下面的Transact- SQL脚本代码:
SELECT @tmpXML.query('
FOR $var IN /Categories/*[position()<=2]
RETURN
ELEMENT CategoryInfo
{
ATTRIBUTE CategoryID {string($var/@CategoryID[1])},
ELEMENT CategoryName {string($var/CategoryName[1])},
ELEMENT Description {string($var/Description[1])}
}
'
) AS CategoryInfo
GO
(8) 上述Transact-SQL脚本中使用了上下文函数position(),通过该函数返回元素Categories中所含的前两项子元素的值。单击【执行】按钮,所得结果如图8.38所示。
图8.38 查询结果
读者如果想要了解与XQuery相关的更多函数及其使用方法,可参见Microsoft提供的联机帮助文档。
8.5.2 使用SQL Server 2005的XML数据类型方法进行查询
为了更好地满足用户使用XML数据的要求,Microsoft SQL Server 2005引入了一种新的XML数据类型。这种数据类型有多种方法:query()、exist()、value()、nodes()和modify(),它们实现了XML查询 (XQuery)规范中最重要的子集部分。下面仍以前面在示例数据库Northwind中创建的数据表xml_Categories为例介绍SQL Server 2005提供的5种XML类型方法。
1. query方法
query方法可用于查询指定元素的XML文档表示。下面就其使用方法进行简单的介绍。
【示例21】query方法的使用。
完整的设计过程如下。
(1) 首先,在【查询编辑器】中输入下面的Transact-SQL脚本:
USE Northwind
GO
SELECT * FROM xml_Categories
GO
(2) 单击【执行】按钮,所获得的查询结果如图8.39所示。
图8.39 查询结果
(3) 单击该记录中的CategoryInfo字段,查看该字段所含的XML文档,如下所示:
<CategoryInfo>
<CategoryName>Beverages</CategoryName>
<Description>
Soft drinks, coffees, teas, beers, and ales
</Description>
</CategoryInfo>
(4) 虽然,表中只有一条记录,不过并不妨碍我们使用该数据表来解释query方法的使用方法。如果此时想查找该记录的整个信息,可在【查询编辑器】中输入下面的Transact-SQL脚本:
USE Northwind
SELECT CategoryInfo.query('CategoryInfo')
FROM xml_Categories
WHERE CategoryID = 1
(5) 单击【执行】按钮可得到与上面一致的查询结果。如果只想查看该记录的类别名称,可输入以下Transact-SQL脚本:
USE Northwind
SELECT CategoryInfo.query('CategoryInfo/CategoryName')
FROM xml_Categories
WHERE CategoryID = 1
上述Transact-SQL脚本中的query函数使用了形如“根元素名/子元素名”的方式来查找子元素的值。需要注意的是,在指定要查询的子元素值时,必须从根元素起开始定位。
(6) 如果想查看与该字段相关的Description子元素的相关信息,同样可以在【查询编辑器】中输入下面的Transact-SQL脚本代码:
USE Northwind
SELECT CategoryInfo.query('CategoryInfo/Description')
FROM xml_Categories
WHERE CategoryID = 1
(7) 单击【执行】按钮运行上述Transact-SQL脚本的结果如下所示:
<Description>Soft drinks, coffees, teas, beers, and ales</Description>
2. value方法
value方法为开发人员提供了直接访问XML文档中元素或属性值的途径。利用该方法,可以在复杂的XML文档中直接获取指定元素或属性的值(即直接获取XML文档中某节点的值)value方法将直接返回一个标量值。value方法的语法如下所示:
value(query_express, SQLType)
其中query_express为欲查询的XML文档节点或节点属性的表达式,需要注意的是,与前面介绍的一样,表示属性时需要在其前面添加一个“@”符号。
【示例22】value方法的使用。
完整的设计过程如下。
(1) 为了更好地说明value方法的使用方法,下面为数据表xml_Categories添加一条新记录。在【查询编辑器】中输入下面的Transact-SQL脚本代码:
USE Northwind
GO
DECLARE @CategoryInfo AS XML
SET @CategoryInfo =
'<CategoryInfo>
<CategoryName>
Condiments
</CategoryName>
<Description class ="baseinfo">
Sweet and savory sauces, relishes, spreads, and seasonings
</Description>
<Description class ="Level">
Level 1 Credited by BeiJing Board Of Health
</Description>
</CategoryInfo>'
INSERT INTO xml_Categories(CategoryID,CategoryInfo)
VALUES(2,@CategoryInfo)
GO
(2) 单击【执行】按钮,向数据表xml_Categories中插入一条新记录。此时,如果想查询第二条记录中有关元素Description的值,可以在【查询编辑器】中输入下面的Transact-SQL脚本代码:
SELECT CategoryInfo.value('(CategoryInfo/Description)[1]', 'VARCHAR(100)') Baseinfo,
CategoryInfo.value('(CategoryInfo/Description)[2]', 'VARCHAR(100)') Level
FROM xml_Categories
WHERE CategoryID =2
(3) 上述Transact-SQL脚本通过访问节点数组Description的第1和第2个元素来获取与该记录相关的两类描述信息。单击【执行】按钮,运行上述Transact-SQL脚本,其结果如图8.40所示。
图8.40 查询结果
(4) 如果想获取第二条记录中属性class的值,可以在【查询编辑器】中输入下面的Transact-SQL脚本:
SELECT CategoryInfo.value('(CategoryInfo/Description/@class)[1]', 'VARCHAR(100)') ClassName1,
CategoryInfo.value('(CategoryInfo/Description/@class)[2]', 'VARCHAR(100)') ClassName2
FROM xml_Categories
WHERE CategoryID =2
(5) 上述代码中查询属性时使用了符号“@”。单击【执行】按钮,运行上述Transact- SQL脚本,其结果如图8.41所示。
图8.41 查询结果
3. modify方法
XML数据类型的modify方法用于修改元素(或称为节点)的值。因此,可以使用modify方法来修改一个xml类型的变量或字段xml文档的相应元素或属性值。该方法的使用语法如下所示:
Modify(XML DML)
其中参数XML DML,指的是XML数据修改语言(Data Modification Language,简称XML DML)。与SQL Server为管理数据库对象提供的DML一样,XML DML主要用于管理XML实例,其中包括插入(Insert)、删除(DELETE)以及替代(REPLACE VAULE OF)三种操作。由于modify方法与XML DML密切相关,因此本节暂不对modify方法的使用方法做过多的介绍,而在8.5.4节中进行详细说明。
4. nodes方法
采用XML数据类型的nodes方法可以轻松地将一个XML数据类型的实例(例如,一个XML变量或字段)转换为一组相互联系的数据,即数据集。换言之,使用node()方法可以将XML中的某组元素转换为一组数据集中的记录。nodes方法使用语法如下所示:
Nodes (XQuery) AS Table(Column)
从其语法形式上可以很容易地看出,Nodes方法可以将一个XML文档转换为表Table中的相应列(字段)。需要注意的是,这里的Table并非一个真正的物理数据表,而是该查询结果集的别名。因此,数据表Table实际上并不存在。
【示例23】nodes方法的使用。
完整的设计过程如下。
(1) 假如要查询数据表xml_Categories中字段CategoryInfo中的CategoryName节点,并将查询得到的结果集转换为以tmpTable为其别名的数据表中的一个字段,可在【查询编辑器】中输入下面的Transact-SQL脚本:
USE Northwind
GO
DECLARE @CategoryInfo AS XML
SELECT @CategoryInfo = CategoryInfo FROM xml_Categories
WHERE CategoryId =1
SELECT CategoryName.value('(/CategoryInfo/CategoryName)[1]','VARCHAR(50)')
AS CategoryName
FROM @CategoryInfo.nodes('/CategoryInfo/CategoryName')
AS tmptable(CategoryName)
GO
上述Transact SQL脚本首先使用一组SELECT语句将数据表xml_Categories中第一条记录的字段CategoryInfo保存到XML类型的变量@CategoryInfo中,然后再使用XML数据类型的方法nodes,将查询结果集命名为tmpTable,同时将指定节点“/CategoryInfo/CategoryName”的值转换为tmpTable中的名为CategoryName的字段。
(2) 单击【执行】按钮,运行上述Transact-SQL脚本代码,其结果如图8.42所示。
图8.42 查询结果
5. exist方法
显然,exist方法是一个用于判断指定XML型结果集中是否存在指定节点的方法。该方法返回的结果包括两种值,即1(当XML型结果集中至少包含一个查询节点时)或0(当XML型查询集中没有包含指定节点时)。
该方法的使用语法如下所示:
exist(‘XQeuryExpression’)
其中XQeuryExpression代表指定的XML型查询语句,该查询语句将生成一组XML型结果集。
【示例24】exist方法的使用。
完整的设计过程如下。
(1) 下面依次来检查数据表xml_Categories中的字段CategoryInfo中存在的节点情况,在【查询编辑器】中输入下面的Transact-SQL脚本:
USE Northwind
GO
SELECT CategoryInfo.exist('/CategoryInfo/CategoryName') AS 是否存在CategoryName节点,
CategoryInfo.exist('/CategoryInfo/Description') AS 是否存在Description节点,
CategoryInfo.exist('CategoryName/Description') AS 节点CategoryName下是否存在Description节点
FROM xml_Categories
GO
(2) 单击【执行】按钮,运行上述Transact-SQL脚本,其结果如图8.43所示。
图8.43 查询结果
8.5.3 启用OPENXML
如果说SQL Server 2005通过FOR XML子句为用户提供了一种将查询结果集转换为XML文档的方法,那么OPENXML记录集函数则为用户提供了一种将XML文档转换,并导入数据表的途径。即使用FOR XML可以把关系型数据检索为XML;而使用OPENXML则可以把XML文档转为关系型数据表。将XML文档转换为关系型数据表的好处之一是,便于对这些数据施加数据表操作(例如执行查询等)。SQL Server 2005进一步提高了原有的OPENXML功能。除了能够处理XML数据类型之外,还进一步提供了对几种新的数据类型的支持,例如用户自定义类型(UDTs)等。用户可以通过OPENXML WITH子句使用OPENXML功能,也可以通过向系统自带的存储过程sp_preparedocument传递一个XML数据类型实例来访问该功能。
实际上,OPENXML功能是Transact-SQL提供的一种XML文档访问功能。在使用OPENXML功能之前,必须首先调用系统存储过程sp_xml_preparedocument 来解析指定的XML文档。该存储过程可以返回被解析XML文档的句柄,通过该句柄,用户就可以像管理关系型数据集一样来管理被解析后的XML文档数据了。
1. OPENXML简介
使用OPENXML的语法如下所示:
OPENXML ( idoc, rowpattern, [flags] )
[ WITH ( <schemaDeclaration> [ ,...n ] | tableName ) ]
<schemaDeclaration> ::=
colName colType [colPattern | metaProperty]
上述语法中主要参数的含义如表8.11所示。
表8.11 主要参数
参数名 |
含 义 |
idoc |
指向XML文档的句柄,可以使用SQL Server 2005系统自带的存储过程来获取该句柄 |
flags |
用于指定XML数据与记录集间的映射关系 |
rowpattern |
用于指定XML文档中哪些节点需要被转换为数据表中的记录 |
schemaDeclaration |
指定需要使用的数据集架构,例如字段及字段类型等 |
tableName |
如果已存在一个具有指定架构的数据表,而且无需对字段类型进行任何限制,此时可以使用一个数据表名来替代前面的XML架构 |
colName |
结果集中的字段名 |
colType |
结果集中字段的数据类型 |
colPattern |
用于说明如何将XML节点映射为结果集中的字段 |
metaProperty |
用于获取与XML节点相关的信息 |
flags参数用于指明XML数据与记录集间的映射关系,具体含义如表8.12所示。
表8.12 flags参数具体含义
flags值 |
含 义 |
0 |
如果没有任何具体要求可以选择0 |
1 |
以属性为中心,即将XML的属性映射为由schemaDeclaration定义的字段 |
2 |
以元素为中心,即将XML中的元素映射为由schemaDeclaration定义的字段 |
8 |
与 XML_ATTRIBUTES 或 XML_ELEMENTS 组合使用(逻辑OR)。在检索的上下文中,该标志指明不应将已消耗的数据复制到溢出属性 @mp:xmltext |
有关与OPENXML方法相关的其他参数,在此不做过多介绍。详情请参见Microsoft提供的联机帮助文档。下面通过示例进一步介绍SQL Server 2005中提供的OPENXML功能。
2. sp_xml_preparedocument系统存储过程简介
常与OPENXML功能配置使用的另一系统存储过程的语法如下所示:
sp_xml_preparedocument hDoc
OUTPUT
[ , xmlText ] [ , xpathNamespaces ]
该系统过程使用的主要参数如表8.13所示。
表8.13 主要参数
参数名 |
含 义 |
hDoc |
用于解析XML文档的句柄 |
xmlText |
需要被解析的XML文档 |
xPathNamespaces |
记录和字段的命名空间表达式 |
3. sp_xml_removedocument系统存储过程简介
完成XML文档到数据表的转换之后,可以使用系统存储过程sp_xml_removedocument 来释放转换句柄所占用的内存资源。该存储过程的使用方法如下所示:
sp_xml_removedocument hDoc
其中hDoc为需要释放的句柄。
【示例25】OPENXML应用举例。
下面通过示例来具体介绍OPENXML功能的使用方法,完整的设计过程如下。
(1) 打开【查询编辑器】,输入以下Transact-SQL脚本代码:
USE Northwind
GO
DECLARE @idoc INT
DECLARE @CategoryInfo xml
SET @CategoryInfo = (SELECT CategoryInfo FROM xml_Categories
WHERE CategoryID = 1)
EXEC sp_xml_preparedocument @idoc OUTPUT, @CategoryInfo,
N'<CategoryInfo/>'
SELECT * FROM OPENXML (@idoc, N'CategoryInfo',2)
WITH
(
CategoryName VARCHAR(50) N'CategoryName',
Description VARCHAR(200) N'Description'
)
EXEC sp_xml_removedocument @idoc
GO
上述Transact-SQL脚本首先将示例数据表xml_Categories中的第一条记录的XML类型字段保存到XML类型变量@CategoryInfo中。然后使用系统存储过程sp_xml_preparedocument获取一个指向XML类型变量@CatgoryInfo的句柄,并指定要检索的XML节点。
(2) 接下来,在FROM OPENXML中指定需要检索的元素名。由于示例数据表xml_Categories中的第一条记录所含XML文档中没有包含任何属性,因此,这里只将根元素<CategoryInfo>中的子元素CategoryName和Description转换为关系型数据集,因此需要将flag设置为2。由于没有现存的数据表可用,这里使用参数schemaDeclaration来定义关系型数据集的架构,其中指定了该数据集中包含的两个字段,分别为CategoryName和Description,并分别定义了这些字段的类型(VARCHAR(50)和VARCHAR(2000))。
(3) 最后使用系统存储过程sp_xml_removedocument释放指定名柄变量@idoc所占用的资源。
(4) 单击【执行】按钮,执行上述Transact-SQL脚本代码,其结构如图8.44所示。
图8.44 查询结果
(5) 继续在【查询编辑器】中输入下面的Transact-SQL脚本代码:
USE Northwind
GO
DECLARE @idoc INT
DECLARE @CategoryInfo xml
SET @CategoryInfo = (SELECT CategoryInfo FROM xml_Categories
WHERE CategoryID = 2)
EXEC sp_xml_preparedocument @idoc OUTPUT, @CategoryInfo,
N'<CategoryInfo/>'
SELECT * FROM OPENXML (@idoc, N'CategoryInfo/Description',1)
WITH
(
ClassType VARCHAR(50) N'@class'
)
EXEC sp_xml_removedocument @idoc
GO
(6) 与上一示例不同,上述Transact-SQL脚本用于将元素<Description>的属性class转换为关系型数据集中的字段ClassType,因此在使用OPENXML方法时需要将flag参数设置为1。单击【执行】按钮,运行上述Transact-SQL脚本,其结果如图8.45所示。
图8.45 查询结果
8.5.4 使用XML DML
1. 基本概念
当前的XQuery 规范包括查询的语法和语义词,但没有提供对XML文档进行修改的功能。为了弥补这一不足,Microsoft在其SQL Server 2005中提供了名为XML数据修改语言(DML)的XML扩展功能,该功能是对XQuery数据修改特性的扩展。SQL Server 2005在其提供的XML命令集中增加了3个关键字:即Insert、Update和Delete。这三个关键字与XML数据类型的modify()方法相互配合可以实现对XML文档的修改功能。
2. XMl DML命令简介
XML DML为XML文档的修改功能提供了以下三种方法。
l xml.modify(Insert):使用xml.modify(Insert)可以向XML数据类型实例中的一组序列节点中插入一个新的节点。该关键字的使用方法如下所示:
Insert Expression1
( {AS FIRST | AS LAST} INTO | AFTER | BEFORE
Expression2 )
其中主要参数如表8.14所示。
表8.14 主要参数
参 数 |
含 义 |
Expression1 |
用于指定欲插入的节点的表达式,需要注意由于插入操作不能针对根节点,所以表达式中不能带有符号“/” |
Expression2 |
指定XML文档中与新插入节点相关的一个节点表达式 |
AS FIRST/LAST |
如果待插入的节点Expression1将要成为Expression2的一个子节点,可使用该参数来指定新节点在Expression2中的位置 |
AFTER/BEFORE |
如果待插入的节点Expression1与Expression2同级,可以使用该参数来指定XML文档中Expression1相对于Expression2的位置 |
l xml.modify(Delete):使用xml.modify(Delete)可以删除指定XQuery表达式中的0个或多个节点。该关键字的使用方法如下所示:
DELETE Expression
其中参数Expression为要删除的节点表达式。
l xml.modify(replace):被用于修改一个指定节点的值。该关键字的使用方法如下所示:
REPLACE value of Expression1 WITH Expression2
其中参数Expression1和Expression2分别表示被替换节点的旧值和用于替换旧值的新值。
下面分别通过示例对上述3个关键字进行介绍。
【示例26】3个关键字的使用。
完整的设计过程如下。
(1) 打开【查询编辑器】,在其中输入以下Transact-SQL脚本:
USE Northwind
GO
INSERT INTO xml_Categories (CategoryID, CategoryInfo)
VALUES (3, '<CategoryInfo></CategoryInfo>')
GO
SELECT CategoryInfo FROM xml_Categories WHERE CategoryID = 3
(2) 上述Transact-SQL脚本在数据表xml_Categories中插入一条新记录,其XML型字段CategoryInfo中只带有一个根节点<CategoryInfo/>。单击【执行】按钮运行上述Transact-SQL脚本,其结果如图8.46所示。
(3) 继续在【查询编辑器】中输入以下Transact-SQL脚本代码:
UPDATE xml_Categories
SET CategoryInfo.modify('Insert (
<CategoryName>Produce</CategoryName>,
<Description>Dried fruit and bean curd</Description>)
AS LAST INTO (/CategoryInfo[1])')
WHERE CategoryID = 3
SELECT CategoryInfo FROM xml_Categories
图8.46 查询结果
(4) 上述Transact-SQL脚本在使用UPDATE更新第三条记录时,使用INSERT命令向原有的<CategoryInfo>节点相继插入CategoryName元素和Description元素。单击【执行】按钮,运行上述Transact-SQL脚本,其结果如图8.47所示。
图8.47 查询结果
(5) 在查询编辑器中输入下面的Transact-SQL脚本:
UPDATE xml_Categories
SET CategoryInfo.modify('REPLACE value of
(/CategoryInfo/Description/text())[1]
WITH “Dried fruit and bean curd and seasoning”')
WHERE CategoryID = 3
SELECT CategoryInfo FROM xml_Categories
(6) 上述Transact-SQL脚本代码使用replace value of关键字对数据表xml_Categories中的第3条记录的CategoryInfo字段的节点/CategoryInfo/Description进行修改,将该元素原来的值Dried fruit and bean curd更改为Dried fruit and bean curd and seasoning如图8.48所示。
(7) 继续在【查询编辑器】中输入下面的Transact-SQL脚本:
USE Northwind
GO
UPDATE xml_Categories
SET CategoryInfo.modify('DELETE /CategoryInfo/Description')
WHERE CategoryID = 3
SELECT CategoryInfo FROM xml_Categories
GO
图8.48 查询结果
(8) 上述Transact-SQL脚本代码使用Delete关键字删除节点/CategoryInfo/Description。单击【执行】按钮,其运行结果如图8.49所示。
图8.49 运行结果
由图8.49可见,原XML文档中的节点Description已被删除。
上面对XML DML的使用方法进行了简要介绍,有关XML DML的更多用法请参见Microsoft提供的联机帮助文档。