当前位置: 首页 > 图文教程 > 数据库 > MSSQL > SQL Server2005的XML数据类型之基础篇

MSSQL
编程管理sql server的帐号
自己改写的一个sql server 2000的分页存储过程
通过SQL定时分析表监控Unix系统性能
SQL Server磁带数据备份
构造SQL Server的安全门
利用索引提高SQLServer数据处理效率
从SQL备份文件中导入现存数据库中
SQL2005较之SQL2000的改进
SQL SERVER2000中订阅与发布的具体操作
SQL Server中解决死锁的新方法介绍
SQL注入漏洞入侵的过程及其防范措施
查询分析器设置断点单步调试存储过程
SQL Server为Web浏览器提供图像
教你在SQL Server中由原子建立分子查询
关于SQL Server业务规则链接技术探讨
SQL Server 管理常用的SQL和T-SQL
探讨SQL Server数据库中空值处理技巧
SQL Server数据库中使用触发器经验谈
四项技术提高SQL Server性能
SQL Server 2000桌面引擎默认配置空口令漏洞

MSSQL 中的 SQL Server2005的XML数据类型之基础篇


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-17   浏览: 63 ::
收藏到网摘: n/a

一、引言

如今,在SQL Server 2005中,XML成为第一流的数据类型。借助于基于XML模式的强类型化支持和基于服务器端的XML数据校验功能,现在

,开发者可以对存储的XML文档进行轻松地远程修改。作为数据库开发者,许多人都必须大量地涉及XML。

如今,在SQL Server 2005中,你能以一种新的数据类型的形式把XML存储在数据库中。

事实上,在SQL Server 2000中就已经包括了一些XML特征。其中,最关键的特征是使用FOR XML语句以XML形式返回结果。SQL Server 2005

的功能则明显不同。在SQL Server 2005中,XML是一种真正的数据类型;这意味着,你可以使用XML作为表和视图中的列,XML可以用于T-SQL语

句中或作为存储过程的参数。现在,你可以直接在数据库中存储、查询和管理XML文件。

更重要的是,现在你还能规定你的XML必须遵从的模式。

在SQL Server 2005中,除了提供机制以校验你的数据库中的XML类型之外,它还允许你描述要被存储的复杂数据类型并且提供一个引擎来

强制施加这些规则。

二、使用XML数据类型

其实,XML数据类型与SQL Server中的其它数据类型并不存在根本的区别。你可以把它用在使用任何普通SQL数据类型的地方。例如,下列

语句创建一个XML变量并用一个XML填充它:

DECLARE @doc XML

SELECT @doc = '<Team name="Braves" />'

另外,你还可以使用一个查询和SQL Server的FOR XML语法来填充一个XML变量:

SELECT @doc =

(SELECT * FROM Person.Contact FOR XML AUTO)

XML数据类型不仅可以作为变量使用,也可以应用于表列中。你还能分配缺省值并且支持NOT NULL约束:

注意:SQL Server 2005的XML功能与SQL Server 2000中具有明显的不同。

把XML数据插入到表格中只需要用字符串形式的XML指定即可。

下列示例插入一组记录:

以下为引用的内容:

INSERT INTO Team (TeamDoc)
VALUES ('
<Team name="Braves">
<Players>
<Pitcher name="John Smoltz"
role="Closer"/>
</Players>
</Team>');
INSERT INTO Team (TeamDoc)
VALUES ('
<Team name="Red Sox">
<Players>
<Pitcher name="Petro Martinez"
role="Starter"/>
</Players>
</Team>');

当在SQL Server 2005中创建XML的实例时,唯一的转换是从一个字符串转换成一个XML类型。同样,沿着相反的方向,你只可以把XML类型

转换成一个字符串类型。在text和ntext类型之间转换是不允许的。

三、XML数据类型的限制

尽管在SQL Server 2005中XML数据类型就象许多其它数据类型一样对待,但是还存在一些如何使用它的具体限制。这些限制是:

· XML类型不能转换成text或ntext数据类型。

· 除了string类型,没有其它数据类型能够转换成XML。

· XML列不能应用于GROUP BY语句中。

· 分布式局部(partitioned)视图不能包含XML数据类型。

· sql_variant实例的使用不能把XML作为一种子类型。

· XML列不能成为主键或外键的一部分。

· XML列不能指定为唯一的。

· COLLATE子句不能被使用在XML列上。

· XML列不能加入到规则中。

· 唯一可应用于XML列的内置标量函数是ISNULL和COALESCE。没有任何其它内置标量函数支持使用XML类型。

· 表中最多只能拥有32个XML列。

· 具有XML列的表不能有一个超过15列的主键。

· 具有XML列的表不能有一个timestamp数据类型作为它们的主键的一部分。

· 存储在数据库中的XML仅支持128级的层次。

四、XML类型方法

到此为止,上面的示例已经展示了XML数据类型仅能用作一种blob类型数据,但是这正是XML数据类型显示其自身力量的地方。XML数据类型

支持使用UDT点(myXML.operation())语法进行调用的若干方法。下表1中列举出所支持的方法。

表格1:XML数据类型方法。

方法名 描述

query  执行一个XML查询并且返回查询的结果

exists  执行一个XML查询,并且如果有结果的话返回值1

value  计算一个查询以从XML中返回一个简单的值

modify  在XML文档的适当位置执行一个修改操作

nodes  允许你把XML分解到一个表结构中

在下面几节中,你要使用一个表Team,它的每一个行中包含一个小组的名字。在每一行中,有一个包含有关于该小组的XML数据的TeamDoc

行:

以下为引用的内容:

CREATE TABLE Team
(
TeamID int identity not null,
TeamDoc XML DEFAULT '<Team />' NOT NULL
)

在这些例子中,我们假定下面的XML文档存在于表中的Braves行中:

<Team name="Braves">
<Players>
<Pitcher name="John Smoltz" role="Closer"/>
<Pitcher name="Russ Ortiz" role="Starter" />
<ThirdBase name="Chipper Jones"
role="Starter" bats="switch"/>
</Players>
</Team> 

query方法

注意:你可以在表和视图列、T-SQL语句或存储过程的参数中使用XML。

这个方法允许你指定一个要计算的Xquery或XPath表达式,该方法的结果是一个XML数据类型对象。它的具体语法形式如下:

query(XQuery)

第一个参数总是一个Xquery表达式。下面的例子使用一个查询来返回一个XML文档-其中包含有关每一个小组的投球手的信息:

SELECT TeamDoc.query('/Team/Players/Pitcher')

FROM Team

这个语句产生如下结果:

以下为引用的内容:
----------------------------------------------
<Pitcher name="John Smoltz" role="Closer" />
<Pitcher name="Russ Ortiz" role="Starter" />
(1 row(s) affected)

这个query方法允许你查询和返回与你指定的表达式相匹配的结点列表。该方法的真正威力来自于XQuery语法,我们将在本文后面再详细讨

论。

exist方法

这个exist方法用于决定是否一个查询能够产生任何结果。这个exist方法的语法形式如下:

exist(XQuery)

当你使用这个exist方法时,它计算这个XQuery查询,并且如果该查询产生任何结果的话返回值1。例如,下面语句查询小组表行中是否

TeamDoc域中存有Starter投手:

下面是简单的Exist语句:

以下为引用的内容:
SELECT Count(*)
FROM Team
WHERE TeamDoc.exist(
'/Team/Players/Pitcher[@role="Starter"]') = 1

value方法

当你不想解释整个查询的结果而只想得到一个标量值时,这个value方法是很有帮助的。这个value方法用于查询XML并且返回一个原子值。

这个value方法的语法如下:

value(XQuery,datatype)

借助于value方法,你可以从XML中得到单个标量值。为此,你必须指定XQuery语句和你想要它返回的数据类型,并且你可以返回除了XML数

据类型外的任何数据类型。例如,如果你想得到每一个小组中的第一个投球手的名字,你可以编写如下形式的查询语句:

进行一次查询以得到单个值

以下为引用的内容:
SELECT TeamDoc.value(
'(/Team/Players/Pitcher/@name)[1]',
'nvarchar(max)')
AS FirstPitcher
FROM Team

在每一个小组的第一个投球手的标量值中的这个查询结果返回值如下:

以下为引用的内容:
FirstPitcher
------------------------------
John Smoltz
(1 row(s) affected)

注意,query和value方法之间的不同在于,query方法返回一个XML数据类型-它包含查询的结果;而value方法返回一个带有查询结果的非

XML数据类型。另外,value方法仅能返回单个值(或标量值)。如果你试图创建一个使用value方法返回多于一个值的XQuery表达式,你将得到一

个错误。

modify方法

尽管XQuery标准并没有提供一种更新XML的机制,但是SQL Server 2005提供了一种方法用于即时地修改一个XML对象的一部分。这意味着,

你不必仅为了修改而检索一个完整的XML文档。为了即时修改一个文档,你可以采用一种结合方式-Modify方法和SQL Server 2005的新的XML数

据修改语言(XML DML)。

Modify方法的语法是:

modify(<XMLDML>)

该方法仅使用一个参数:XML DML语句。XML DML也类似于SQL的insert,update和delete语法,但是并不一样。例如,你可以通过使用

insert DML语句来修改XML:

以下为引用的内容:
SET @doc.modify('
insert <Pitcher name="Jaret Wright"/> as last
into (/Team/Players)[1]
')

另外,你还可以通过调用一个UPDATE语句并修改一个XML列来实现同样目的:

修改一个XML文档而不完全替换它:

以下为引用的内容:
UPDATE Team
SET TeamDoc.modify('
insert <Pitcher name="Jaret Wright"/> as last
into (/Team/Players)[1]
')
WHERE TeamDoc.exist('/Team[@name="Braves"]') = 1 

注意,在这个UPDATE语句中的SET子句并不遵循你过去编写SQL时所使用的SET x = y 模式。该语法假定,你能够提供一个完全新的值来代

替旧值-这在XML情况下意味着要使用一个完全新的文档来代替旧文档。当使用XML类型时,Modify方法可以即时修改原始文档。也就是说,对于

SQL Server来说,不必要对每一次修改都试图替换整个文档。在本例中的SET语法反映了一种即时修改一个文档的更为有效的方式。

共有三种XML DML语句:insert,update和delete。这三个语句分别用于插入,更新和删除一个XML对象的部分。每一个方法的语法类似于

SQL,但是也有一些明显的差别。

下面是相应于insert语句的语法:

以下为引用的内容:
insert
InsertExpression (
{{as first | as last}
into | after | before} LocationExpression
)

紧跟着这个insert语句的是你想要插入的XML(InsertExpression)。接下来,你需要指定你想怎样插入该XML。你的选择是into,after或

before。其中,before和after子句指令数据库把InsertExpression作为LocationExpression的一个兄弟(sibling)插入。before或after则指

定是在LocationExpression的前面还是后面插入它:

以下为引用的内容:
SET @doc.modify('
insert <Pitcher role="Starter"
name="Jaret Wright"/>
before (/Team/Players/Pitcher)[1]
')

这个into子句把InsertExpression作为LocationExpression的一个孩子结点插入。可选子句as first和as last用于指定在该孩子结点中插

入的位置:

在小组内进行插入

以下为引用的内容:
SET @doc.modify('
insert <Pitcher role="Starter"
name="Jaret Wright"/>
into (/Team/Players)[1]
')

在小组内进行插入,指定它应该

作为最后一个元素插入

以下为引用的内容:
SET @doc.modify('
insert <Pitcher role="Starter"
name="Jaret Wright"/>
as last into (/Team/Players)[1]
')

delete语句的语法很直接:

delete LocationExpression

这个LocationExpression指定要从XML数据中删除什么内容。例如,要删除所有的投球手:

SET @doc.modify('delete/Team/Player/Pitcher')

因为查询指定所有的投球手元素,所以它们将被全部删除。如果你想仅删除一个元素,那么你可以指定标识属性。例如,为了仅删除投球

手John Smoltz,你可以编写如下的delete语句:

以下为引用的内容:
SET @doc.modify('
delete /Team/Players/Pitcher[@name="John Smoltz"]
')

你可以使delete语句删除单个属性。例如,为了删除针对投球手John Smoltz的role属性,相应的XML DML看上去如下所示:

以下为引用的内容:
SET @doc.modify('
delete /Team/Players/Pitcher[
@name="John Smoltz"]/@role')

最后,replace value语句描述了对XML数据的修改。这个replace value语句的语法如下:

以下为引用的内容:
replace value of
OriginalExpression
with
ReplacementValue | if

这个replace value语句用来修改在XML中的值。唯一可能的值是一个标签的内容或一个属性的值。这个OriginalExpression必须解析为单

个结点或属性。这个ReplacementValue通常是一个要代替的值。代替一个结点的内容要求使用text()函数的XQuery表达式来指定你想代替一个

结点的文本。例如,为了替换一个投球手的内部文本(inner text),你可以编写类似如下的Modify语句:

以下为引用的内容:
DECLARE @doc XML
SELECT @doc = '
<Team name="Braves">
<Players>
<Pitcher name="John Smoltz" role="Closer">
With team since 1989
</Pitcher>
</Players>
</Team>'
SET @doc.modify('
replace value of (/Team/Players/Pitcher[
@name="John Smoltz"]/text())[1]
with "May start in 2005"
')

修改属性是直接的:你只需要使用XQuery表达式来解析单个属性。例如,为了使用"Starter"替换投球手John Smoltz的role属性的值,你

可以编写如下的语句:

以下为引用的内容:
SET @doc.modify('
replace value of (/Team/Players/Pitcher[
@name="John Smoltz"]/@role)[1]
with "Starter"
')

replace value语法也支持条件替换,这可以通过在replace value语句的with子句内使用if…then…else语法实现。例如,如果John

Smoltz是一个Closer的话,把他的role替换为Starter;但是如果他不是一个Starter的话,则把role属性修改为Closer;那么,你可以编写如

下的代码:

以下为引用的内容:
SET @doc.modify('
replace value of (/Team/Players/Pitcher[
@name="John Smoltz"]/@role)[1]
with (
if (/Team/Players/Pitcher[
@name="John Smoltz"]/@role = "Closer") then
"Starter"
else
"Closer"
)
')

nodes方法

nodes方法用于把一组由一个查询返回的结点转换成一个类似于结果集的表中的一组记录行。该方法的语法如下:

nodes (XQuery) Table(Column)

这里,XQuery是选择要暴露为一个结果集的结点的表达式。Table和Column用于指定结果集中的名字。注意,你仅可以操作一列并且它的自

动类型为XML。例如,为了查询并得到每一个投球手的信息,你可以编写如下的代码:

以下为引用的内容:
DECLARE @doc XML
SELECT @doc = '
<Team name="Braves">
<Players>
<Pitcher name="John Smoltz" role="Closer">
With team since 1989
</Pitcher>
</Players>
</Team>'
SELECT Team.player.query('.') as Pitcher
FROM @doc.nodes('/Team/Players/Pitcher')
Team(player) 

这些在单个结果集中的结果包含相应于每一个投球手的元素的行数据:

以下为引用的内容:
Pitcher
--------------------------------------------
<Pitcher name="John Smoltz" role="Closer" />
<Pitcher name="Russ Ortiz" role="Starter" />
(2 row(s) affected)

注意,上面你使用了query方法把这些结点返回到结果中。其原因在于,一个nodes方法的结果可能仅能为XML方法(查询,修改,删除和更

新)或IS NULL和IS NOT NULL语句所参考。

一般地,你可以使用nodes方法把XML分解为一组更为有用的结果。例如,你可以使用nodes方法得到运动员的结点,然后使用value方法检

索它们以便得到作为标量数据的单个值:

以下为引用的内容:
SELECT Team.player.value(
'./@name', 'nvarchar(10)') as Name,
Team.player.value('./@role', 'nvarchar(10)') as
PlayerRole
FROM @doc.nodes('/Team/Players/Pitcher')
Team(player)

这会产生如下的结果:

以下为引用的内容:

Name PlayerRole
--------------- ---------------
John Smoltz Closer
Russ Ortiz Starter
(2 row(s) affected)