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

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介:
一、 引言

  如今,在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约束:

CREATE TABLE Team 
(
TeamID int identity not null,
TeamDoc xml DEFAULT '<Team />' 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)













本文转自朱先忠老师51CTO博客,原文链接: http://blog.51cto.com/zhuxianzhong/60088,如需转载请自行联系原作者




相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
相关文章
|
1月前
|
SQL 存储 缓存
SQL Server 数据太多如何优化
11种优化方案供你参考,优化 SQL Server 数据库性能得从多个方面着手,包括硬件配置、数据库结构、查询优化、索引管理、分区分表、并行处理等。通过合理的索引、查询优化、数据分区等技术,可以在数据量增大时保持较好的性能。同时,定期进行数据库维护和清理,保证数据库高效运行。
|
2月前
|
SQL 移动开发 Oracle
SQL语句实现查询连续六天数据的方法与技巧
在数据库查询中,有时需要筛选出符合特定时间连续性条件的数据记录
|
2月前
|
SQL 存储 关系型数据库
添加数据到数据库的SQL语句详解与实践技巧
在数据库管理中,添加数据是一个基本操作,它涉及到向表中插入新的记录
|
2月前
|
SQL 数据挖掘 数据库
SQL查询每秒的数据:技巧、方法与性能优化
id="">SQL查询功能详解 SQL(Structured Query Language,结构化查询语言)是一种专门用于与数据库进行沟通和操作的语言
|
2月前
|
SQL 监控 数据处理
SQL数据库数据修改操作详解
数据库是现代信息系统的重要组成部分,其中SQL(StructuredQueryLanguage)是管理和处理数据库的重要工具之一。在日常的业务运营过程中,数据的准确性和及时性对企业来说至关重要,这就需要掌握如何在数据库中正确地进行数据修改操作。本文将详细介绍在SQL数据库中如何修改数据,帮助读者更好
410 4
|
2月前
|
SQL 数据处理 数据库
SQL Server 数据类型转换详解
SQL Server 数据类型转换详解
143 2
|
2月前
|
SQL 关系型数据库 MySQL
SQL批量插入测试数据的几种方法?
SQL批量插入测试数据的几种方法?
134 1
|
2月前
|
SQL 分布式计算 关系型数据库
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
103 0
|
2月前
|
SQL 分布式计算 关系型数据库
Hadoop-23 Sqoop 数据MySQL到HDFS(部分) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-23 Sqoop 数据MySQL到HDFS(部分) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
47 0
|
2月前
|
SQL 分布式计算 关系型数据库
Hadoop-22 Sqoop 数据MySQL到HDFS(全量) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-22 Sqoop 数据MySQL到HDFS(全量) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
57 0