Fork me on GitHub
SQL对Xml字段的操作

SQL对Xml字段的操作

 

T-Sql操作Xml数据

一、前言

SQL Server 2005 引入了一种称为 XML 的本机数据类型。用户可以创建这样的表,它在关系列之外还有一个或多个 XML 类型的列;此外,还允许带有变量和参数。为了更好地支持 XML 模型特征(例如文档顺序和递归结构),XML 值以内部格式存储为大型二进制对象 (BLOB)。

用户将一个XML数据存入数据库的时候,可以使用这个XML的字符串,SQL Server会自动的将这个字符串转化为XML类型,并存储到数据库中。

随着SQL Server 对XML字段的支持,相应的,T-SQL语句也提供了大量对XML操作的功能来配合SQL Server中XML字段的使用。本文主要说明如何使用SQL语句对XML进行操作。

二、定义XML字段

在进行数据库的设计中,我们可以在表设计器中,很方便的将一个字段定义为XML类型。需要注意的是,XML字段不能用来作为主键或者索引键。同样,我们也可以使用SQL语句来创建使用XML字段的数据表,下面的语句创建一个名为“docs”的表,该表带有整型主键“pk”和非类型化的 XML 列“xCol”:

CREATE TABLE docs (pk INT PRIMARY KEY, xCol XML not null)

XML类型除了在表中使用,还可以在存储过程、事务、函数等中出现。下面我们来完成我们对XML操作的第一步,使用SQL语句定义一个XML类型的数据,并为它赋值:

declare @xmlDoc xml;

set @xmlDoc='<book id="0001">

<title>C Program</title>

<author>David</author>

<price>21</price>

</book>'

三、查询操作

在定义了一个XML类型的数据之后,我们最常用的就是查询操作,下面我们来介绍如何使用SQL语句来进行查询操作的。

在T-Sql中,提供了两个对XML类型数据进行查询的函数,分别是query(xquery)和value(xquery, dataType),其中,query(xquery)得到的是带有标签的数据,而value(xquery, dataType)得到的则是标签的内容。接下类我们分别使用这两个函数来进行查询。

1、使用query(xquery) 查询

我们需要得到书的标题(title),使用query(xquery)来进行查询,查询语句为:

select @xmlDoc.query('/book/title')

运行结果如图:

clip_image001

2、使用value(xquery, dataType) 查询

同样是得到书的标题,使用value函数,需要指明两个参数,一个为xquery, 另一个为得到数据的类型。看下面的查询语句:

select @xmlDoc.value('(/book/title)[1]', 'nvarchar(max)')

运行结果如图:

clip_image002

3、查询属性值

无论是使用query还是value,都可以很容易的得到一个节点的某个属性值,例如,我们很希望得到book节点的id,我们这里使用value方法进行查询,语句为:

select @xmlDoc.value('(/book/@id)[1]', 'nvarchar(max)')

运行结果如图:

clip_image003

4、使用xpath进行查询

xpath是.net平台下支持的,统一的Xml查询语句。使用XPath可以方便的得到想要的节点,而不用使用where语句。例如,我们在@xmlDoc中添加了另外一个节点,重新定义如下:

set @xmlDoc='<root>

<book id="0001">

<title>C# Program</title>

<author>Jerry</author>

<price>50</price>

</book>

<book id="0002">

<title>Java Program</title>

<author>Tom</author>

<price>49</price>

</book>

</root>'

--得到id为0002的book节点

select @xmlDoc.query('(/root/book[@id="0002"])')

上面的语句可以独立运行,它得到的是id为0002的节点。运行结果如下图:

clip_image001[6]

四、修改操作

SQL的修改操作包括更新和删除。SQL提供了modify()方法,实现对Xml的修改操作。modify方法的参数为XML修改语言。XML修改语言类似于SQL 的Insert、Delete、UpDate,但并不一样。

1、修改节点值

我们希望将id为0001的书的价钱(price)修改为100, 我们就可以使用modify方法。代码如下:

set @xmlDoc.modify('replace value of (/root/book[@id=0001]/price/text())[1] with "100"')

--得到id为0001的book节点

select @xmlDoc.query('(/root/book[@id="0001"])')

注意:modify方法必须出现在set的后面。运行结果如图:

clip_image005

2、删除节点

接下来我们来删除id为0002的节点,代码如下:

--删除节点id为0002的book节点

set @xmlDoc.modify('delete /root/book[@id=0002]')

select @xmlDoc

运行结果如图:

clip_image007

3、添加节点

很多时候,我们还需要向xml里面添加节点,这个时候我们一样需要使用modify方法。下面我们就向id为0001的book节点中添加一个ISBN节点,代码如下:

--添加节点

set @xmlDoc.modify('insert <isbn>78-596-134</isbn> before (/root/book[@id=0001]/price)[1]')

select @xmlDoc.query('(/root/book[@id="0001"]/isbn)')

运行结果如图:

clip_image008

4、添加和删除属性

当你学会对节点的操作以后,你会发现,很多时候,我们需要对节点进行操作。这个时候我们依然使用modify方法,例如,向id为0001的book节点中添加一个date属性,用来存储出版时间。代码如下:

--添加属性

set @xmlDoc.modify('insert attribute date{"2008-11-27"} into (/root/book[@id=0001])[1]')

select @xmlDoc.query('(/root/book[@id="0001"])')

运行结果如图:

clip_image010

如果你想同时向一个节点添加多个属性,你可以使用一个属性的集合来实现,属性的集合可以写成:(attribute date{"2008-11-27"}, attribute year{"2008"}),你还可以添加更多。这里就不再举例了。

5、删除属性

删除一个属性,例如删除id为0001 的book节点的id属性,我们可以使用如下代码:

--删除属性

set @xmlDoc.modify('delete root/book[@id="0001"]/@id')

select @xmlDoc.query('(/root/book)[1]')

运行结果如图:

clip_image011

6、修改属性

修改属性值也是很常用的,例如把id为0001的book节点的id属性修改为0005,我们可以使用如下代码:

--修改属性

set @xmlDoc.modify('replace value of (root/book[@id="0001"]/@id)[1] with "0005"')

select @xmlDoc.query('(/root/book)[1]')

运行结果如图:

clip_image012

OK,经过上面的学习,相信你已经可以很好的在SQL中使用Xml类型了,下面是我们没有提到的,你可以去其它地方查阅:exist()方法,用来判断指定的节点是否存在,返回值为true或false; nodes()方法,用来把一组由一个查询返回的节点转换成一个类似于结果集的表中的一组记录行。

 

 

作者:齐飞 
日期:2008年11月27日 
参考资料:SQL Server联机丛书、MSDN、《数据库与SQL Server 2005教程》(清华大学出版社,钱雪忠编著) 
版权归作者所有,转载请注明出处。

 

2010年9月24日更新,修改了内容的显示方式。

如果认为此文对您有帮助,别忘了支持一下哦!

作者:OoC
声明:本博客原创文字只代表本人工作中在某一时间内总结的观点或结论,与本人所在单位没有直接利益关系。非商业,未授权,贴子请以现状保留,转载时必须保留此段声明,且在文章页面明显位置给出原文连接。
 
标签: Sql对Xml操作SqlXmlSQL Server中使用Xml类型Sql Xml

数据库开发

 
摘要: 在MSDTC中访问OLE DB数据库的时候,会抛出异常,异常信息大概是:"Microsoft.Jet.OLEDB.4.0”提供程序不支持 ITransactionLocal 接口。本地事务不可用于当前提供程序,或者是与基础事务通信失败。 原来,在创建OLE DB数据库连接的时候,默认是打开了事务的(automatic transaction enlistment),所以如果放在MSDTC中会出现...阅读全文
posted @ 2013-01-26 16:28 OoC 阅读(24) | 评论 (0) 编辑
 
摘要: 原文链接:http://www.cftea.com/c/2007/08/6HLN4P3VBKA1W2EA.asp“自定义函数”是我们平常的说法,而“用户定义的函数”是 SQL Server 中书面的说法。SQL Server 2000 允许用户创建自定义函数,自定义函数可以有返回值。自定义函数分为:标量值函数或表值函数如果 RETURNS 子句指定一种标量数据类型,则函数为标量值函数。可以使用多条 Transact-SQL 语句定义标量值函数。如果 RETURNS 子句指定 TABLE,则函数为表值函数。表值函数又可分为:内嵌表值函数(行内函数)或多语句函数如果 RETURNS 子句指定的 T阅读全文
posted @ 2012-09-19 14:54 OoC 阅读(43) | 评论 (0) 编辑
 
摘要: 原文地址:http://blog.csdn.net/kiki113/article/details/4105929行列转换等经典SQL语句1.--行列转换原表: 姓名 科目 成绩 张三语文80张三 数学 90 张三 物理 85 李四语文 85 李四物理 82 李四英语 90李四政治 70 王五英语 90转换后的表: 姓名 数学 物理 英语 语文 政治 李四082908570 王五 0090 0 0 张三 90 850 80 0实例:create table cj --创建表cj( ID Int IDENTITY (1,1) not null, --创建列ID,并且每次新增一条记录就会加1...阅读全文
posted @ 2012-05-25 14:19 OoC 阅读(78) | 评论 (0) 编辑
 
摘要: 范式的作用:消除数据冗余、更新异常、插入异常和删除异常。1NF如果一个关系模式R的所有属性都是不可分的基本数据项,则R∈1NF。数据库表中的字段都是单一属性的,不可再分。这个单一属性由基本类型构成,包括整型、实数、字符型、逻辑型、日期型等。不满足第一范式就不是关系型数据库!2NF若关系模式R∈1NF,并且每一个非主属性都完全函数依赖于R的码,则R∈2NF表中的属性必须完全依赖于全部主键,而不是部分主键。所以只有一个主键的表如果符合第一范式,那一定是第二范式。3NF在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。所谓传递函数依赖,指的是如果存在&q阅读全文
posted @ 2012-04-20 17:22 OoC 阅读(283) | 评论 (0) 编辑
 
摘要: 原文链接:http://www.it118.org/Specials/c9fba99e-4401-49cf-8256-ac3c1a34c0d9/cf2a7ceb-1815-43fe-8810-47af11ac65a9.htm有两种方法可以是实现,而且不使用游标.下面两种方法性能远好于游标.1.INSERT INTO SELECT 这种方法常用在目标表已经存在数据库中.需要从源表把数据插入到目标表的情况.如果目标表和源表的列相同,就不必列出数据列了.USE AdventureWorks GO ----Create TestTable CREATE TABLE TestTable (FirstNa阅读全文
posted @ 2012-04-06 10:32 OoC 阅读(346) | 评论 (0) 编辑
 
摘要: C#中用Guid.NewGuid().ToString()Sql中用NEWID()以上方法生成的是36位的GUID,如果需要转换成32位,则需要替换掉其中的'-'字符。Sql中的方法:replace(newid(), '-', '')------------------------------------------ GUID(全局统一标识符)是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。通常平台会提供生成GUID的API。生成算法很有意思,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字。GUID的唯一缺陷在于阅读全文
posted @ 2012-04-06 10:30 OoC 阅读(1734) | 评论 (0) 编辑
 
摘要: IF ELSE 语句IF ELSE 是最基本的编程语句结构之一几乎每一种编程语言都支持这种结构而它在用于对从数据库返回的数据进行检查是非常有用的TRANSACT-SQL 使用IF ELSE的例子如下语法if (condition)begin(statement block)endelse if (condition)beginstatement block)endelsebegin(statement block)end注意当所指定的条件为真时对应的BEGIN END 语句块就会被执行同时你也应该注意将每一个语句缩进一定量的空格是一种很好的编程习惯它可以极大的提向你的程序的易读性和由于易读性不阅读全文
posted @ 2012-03-29 12:04 OoC 阅读(123) | 评论 (0) 编辑
 
摘要: FOR XML PATH 有的人可能知道有的人可能不知道,其实它就是将查询结果集以XML形式展现,有了它我们可以简化我们的查询语句实现一些以前可能需要借助函数活存储过程来完成的工作。那么以一个实例为主.一.FOR XML PATH 简单介绍那么还是首先来介绍一下FOR XML PATH ,假设现在有一张兴趣爱好表(hobby)用来存放兴趣爱好,表结构如下:接下来我们来看应用FOR XML PATH的查询结果语句如下:SELECT*FROM@hobbyFORXMLPATH 结果:<row><hobbyID>1</hobbyID><hName>爬山&阅读全文
posted @ 2012-03-14 10:26 OoC 阅读(37) | 评论 (0) 编辑
 
摘要: 原文地址:http://space.itpub.net/16436858/viewspace-624449递归CTE是SQL SERVER 2005中重要的增强之一。一般我们在处理树,图和层次结构的问题时需要用到递归查询。 CTE的语法如下1WITHCTEAS2(3SELECTEmpId,ReportTo,FNameFROMEmployWHEREEmpId=14UNIONALL5SELECTemp.EmpId,emp.ReportTo,emp.FNameFROMCTEJOINEmployasempONCTE.EmpId=emp.ReportTo6)递 归CTE最少包含两个查询(也被称为成员)。阅读全文
posted @ 2012-02-20 12:35 OoC 阅读(127) | 评论 (0) 编辑
 
摘要: 原文地址:http://space.itpub.net/7899089/viewspace-702803有两个意义上的重复记录,一是完全重复的记录,也即所有字段均重复的记录,二是部分关键字段重复的记录,比如Name字段重复,而其他字段不一定重复或都重复可以忽略。 1、对于第一种重复,比较容易解决,使用 select distinct * from tableName 就可以得到无重复记录的结果集。 如果该表需要删除重复的记录(重复记录保留1条),可以按以下方法删除 select distinct * into #Tmp from tableName...阅读全文
posted @ 2012-02-08 14:00 OoC 阅读(1502) | 评论 (0) 编辑
 
摘要: sql server 跨服务器查询,很实用阅读全文
posted @ 2012-01-14 22:27 OoC 阅读(63) | 评论 (0) 编辑
 
摘要: Maybe not a bug... but it still sucks!阅读全文
posted @ 2011-10-18 18:32 OoC 阅读(99) | 评论 (0) 编辑
 
摘要: 今天同学问我这个该怎么处理,我觉得对它进行转换:WITH T1 AS(SelectConvert(DateTime,('2011-6-10 '+CONVERT(varchar(100), 登记时间, 24))) AS 时间,*From[采购_使用计划])Select T1.*FROM T1Where 时间 Between'2011-6-10 09:00:00'AND'2011-6-10 10:00:00' 如果不指定日期也是可以的,默认为1900-1-1.经过测试可用,不知道效率如何。阅读全文
posted @ 2011-06-20 20:31 OoC 阅读(343) | 评论 (0) 编辑
 
摘要: 其实我们一直在使用SqlServer的连接池。在连接字符串中,Pooling为是否启用连接池,默认值为true,表示启用。 与连接池相关的两个重要参数是 Min Pool Size和 Max Pool Size ,分别是池中的最小连接数和池中的最大连接数,默认值分别是0和100。 在我们创建一个连接的实例,并调用Open()方法时,连接池管理程序会在连接池中找到一个可用的连接;当调用Close()方法时,连接池管理程序又将连接返回到连接池中,以供下一次调用Open()方法时使用。 另外,连接字符串中的 Connection Lifetime 为连接池中的连接设置了生命周期。它的默认值为0。当.阅读全文
posted @ 2011-06-18 22:43 OoC 阅读(2480) | 评论 (0) 编辑
 
摘要: 禁止VIA协议就可以了,05和08一样。开始-》Sql server 2005-》配置工具-》SQL Server Configuration Manager-》sql协议-》禁止VIA阅读全文
posted @ 2011-05-06 11:21 OoC 阅读(695) | 评论 (0) 编辑
 
摘要: 前言C#常用来开发数据管理类软件,所以学会在C#程序中使用数据库是非常有必要的。目前微软的两个常用数据库软件分别是Access和Sql Server。读者可以自行了解这两种数据库的优劣点,笔者不做过多说明。这两种数据库也是在做开发时最常用的。C#访问数据库是通过ADO.NET实现的。ADO.NET 是一组向 .NET Framework 程序员公开数据访问服务的类。ADO.NET 为创建分布式数据...阅读全文
posted @ 2010-05-15 22:01 OoC 阅读(153) | 评论 (0) 编辑
 
摘要: T-Sql操作Xml数据 一、前言 SQL Server 2005 引入了一种称为 XML 的本机数据类型。用户可以创建这样的表,它在关系列之外还有一个或多个 XML 类型的列;此外,还允许带有变量和参数。为了更好地支持 XML 模型特征(例如文档顺序和递归结构),XML 值以内部格式存储为大型二进制对象 (BLOB)。 用户将一个XML数据存入数据库的时候,可以使用这个XML的字符串,SQ...阅读全文
posted @ 2008-11-27 16:59 OoC 阅读(12314) | 评论 (18) 编辑
posted on 2013-03-30 14:14  HackerVirus  阅读(360)  评论(0编辑  收藏  举报