SqlServer XML数据类型DML相关操作(图文结合)

XML操作很少用到,最近查询个语句,还得到官网查看用法。所以按照官方把相关的DML都操作一遍,作为记录!~


--  测试数据  
--  DROP TABLE #XMLTab  
CREATE TABLE #XMLTab(colxml XML) 
GO 
INSERT INTO #XMLTab   
SELECT N'  
<Record dt="2015-05-05">  
  <Exception type="RING_BUFFER_EXCEPTION">  
    <Task address="0x0062B8E8" />  
    <Error>9003</Error>  
    <Severity>error</Severity>
  </Exception>  
  <Exception type="BUFFER_EXCEPTION">  
    <Task address="0xC452BB39" />  
    <Error>8008</Error>  
    <Severity>true</Severity>
    <Other>00</Other>
  </Exception>  
</Record>'  
GO 
INSERT INTO #XMLTab   
SELECT N'  
<p1:Record dt="2015-05-06" xmlns:p1="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription">  
  <p1:Exception type="RING_BUFFER_EXCEPTION">  
    <p1:Task address="0x0062B8E8" />  
    <p1:Error>9003</p1:Error>  
    <p1:Severity>error</p1:Severity>
  </p1:Exception>  
  <p1:Exception type="BUFFER_EXCEPTION">  
    <p1:Task address="0xC452BB39" />  
    <p1:Error>8008</p1:Error>  
    <p1:Severity>true</p1:Severity> 
	<p1:Other>00</p1:Other> 
  </p1:Exception>  
</p1:Record>'  
GO 


‘XML 数据修改语言 (XML DML)‘

--节点插入

insert Expression1({asfirst | as last} into | after| before Expression2 )

 

--删除XML实例的节点         

delete Expression             

 

--在文档中更新节点的值

replace value of Expression1with Expression2


--	在根路径"/Record/"的第一个"/Exception"下,添加删除一个元素"<Address>".还可以使用{as first | as last}指定位置
UPDATE #XMLTab SET colxml.modify('insert <Address>insert test 1</Address> into (/Record/Exception)[1]');
UPDATE #XMLTab SET colxml.modify('insert <Address>insert test 1</Address> as first into (/Record/Exception)[1]');

--	删除所有元素"Address"
UPDATE #XMLTab SET colxml.modify('delete /Record/Exception[1]/Address');
UPDATE #XMLTab SET colxml.modify('delete /Record/Exception[1]/Address[1]');
技术分享

--	在根路径"/Record/"的第二个"/Exception"下,添加删除一个元素"<Address>"
UPDATE #XMLTab SET colxml.modify('insert <Address>insert test 1</Address> into (/Record/Exception)[2]');

--	删除第二个节点"/Exception"下的所有元素"Address"
UPDATE #XMLTab SET colxml.modify('delete /Record/Exception[2]/Address');
UPDATE #XMLTab SET colxml.modify('delete /Record/Exception[2]/Address[1]');


--	删除"/Record/Exception/"下的第2个元素(即在Exception中第二行的删除)
UPDATE #XMLTab SET colxml.modify('delete /Record/Exception/*[2]')

--	删除所有路径"/Record/Exception"下的元素"<Address>"
UPDATE #XMLTab SET colxml.modify('delete /Record/Exception/Address[1]');
UPDATE #XMLTab SET colxml.modify('delete /Record/Exception/Address');

各种路径表达式都指定“[1]”或者“[2]”等,要求每次只返回单个目标。


在重新删除创建测试表


--	插入一个元素变量(连续执行4次,方便下面测试)
DECLARE @newFeatures xml;
SET @newFeatures = N'<Address></Address>'

UPDATE #XMLTab SET colxml.modify('insert sql:variable("@newFeatures") into (/Record/Exception)[1]');
技术分享

--	插入一个属性到元素"<Address />"(接上步操作)(多个元素相同,以Address[1]/[2]/[3]/[4]区分)
UPDATE #XMLTab SET colxml.modify('insert attribute attrName {"attributeA" } into (/Record/Exception/Address[1])[1]');
UPDATE #XMLTab SET colxml.modify('insert attribute attrName {"attributeB" } into (/Record/Exception/Address[2])[1]');
UPDATE #XMLTab SET colxml.modify('insert attribute attrName {"attributeA" } into (/Record/Exception/Address[3])[1]');
UPDATE #XMLTab SET colxml.modify('insert attribute attrName {"attributeB" } into (/Record/Exception/Address[4])[1]');
技术分享

--	插入一个属性到元素"<Address />",其中条件为[attrName="attributeB"],(每个元素以Address[1]/[2]/[3]/[4]区分)
UPDATE #XMLTab SET colxml.modify('
	insert attribute attrName2 {"0.5" } 
	into (/Record/Exception/Address[4][@attrName="attributeB"])[1]');--成功:第四个Address,attrName="attributeB"

UPDATE #XMLTab SET colxml.modify('
	insert attribute attrName3 {"0.5" } 
	into (/Record/Exception/Address[4][@attrName="attributeA"])[1]');--失败:第四个Address,attrName<>"attributeA"
技术分享
--	删除路径"/Record/Exception/Address"中"Address"的属性"attrName"(所有)
UPDATE #XMLTab SET colxml.modify('delete /Record/Exception/Address/@attrName');
UPDATE #XMLTab SET colxml.modify('delete /Record/Exception/Address/@attrName2');
技术分享
--	变量插入属性值
DECLARE @Hrs FLOAT        
SET @Hrs =0.5

UPDATE #XMLTab SET colxml.modify('insert attribute attrName {sql:variable("@Hrs")} into (/Record/Exception/Task)[1]');
技术分享
--	插入多个属性值
UPDATE #XMLTab SET colxml.modify('
insert (
	attribute attrName2 {"0.5" },
	attribute attrName3 {".2"}  
	)
into (/Record/Exception/Task)[1]');
技术分享

--	插入注释元素(在第3个Address后插入)
UPDATE #XMLTab SET colxml.modify('insert <!-- some comment --> after (/Record/Exception/Address[3])[1]');
技术分享

--	使用"before"在跟目录前(头部)插入处理指令
UPDATE #XMLTab SET colxml.modify('insert <?Program = "Instructions.exe" ?> before (/Record)[1]');
技术分享

--	还可以利用"after" 和 "before" 的方法插入一个元素
UPDATE #XMLTab SET colxml.modify('insert <Address></Address> after (/Record/Exception/Address[1])[1]');
UPDATE #XMLTab SET colxml.modify('insert <Address></Address> before (/Record/Exception/Address[1])[1]');
技术分享

--	添加删除文本(添加文本后,该元素格式显示成一行)
UPDATE #XMLTab SET colxml.modify('insert text{"Product Catalog Description"} as first into (/Record/Exception)[1]');

--	删除后查看,格式正常
UPDATE #XMLTab SET colxml.modify('delete /Record/Exception/text()');

--	以下为添加后的格式
技术分享

--	按条件更改增加属性:
--如果"/Record/Exception/Address[3]"的属性attrName="attributeB",则增加属性attrName="10",否则增加属性attrName="50"
UPDATE #XMLTab SET colxml.modify('
insert
if (/Record/Exception/Address[3][@attrName="attributeB"])
	then attribute attrName {"10"}
else 
	attribute attrName {"50"}
as first into (/Record/Exception/Address[3])[1] ');
技术分享
--	将元素"<Error>9003</Error>"中的文本值"9003"改为"10000"()
UPDATE #XMLTab SET colxml.modify('replace value of (/Record/Exception/Error[1]/text())[1] with "10000" ');

--	将元素"Task"的属性"address"的值改为"100"
UPDATE #XMLTab SET colxml.modify('replace value of (/Record/Exception/Task/@address)[1] with "100" ');
UPDATE #XMLTab SET colxml.modify('replace value of (/Record/Exception/Task[1]/@address)[2] with "999" ');
技术分享

--如果/Record/路径下第一个Exception中,元素Address个数大于3,则更新Exception[1]属性type为"10.0"否则为"20.0"
UPDATE #XMLTab SET colxml.modify('
  replace value of (/Record/Exception[1]/@type)[1]
  with (
       if (count(/Record/Exception[1]/Address) > 3) then "10.0"
       else "20.0"
  )');
技术分享




-------------------------------------------------------------------------------------
以下为XML相关查询
-------------------------------------------------------------------------------------

--	查询某个元素中的所有所有子项
SELECT colxml.query('/Record/Exception') FROM #XMLTab

SELECT colxml.query('//Record/Exception/Address') FROM #XMLTab
--图为第二个查询语句的结果
技术分享
--	元素带前缀的查询.之前在临时表插入的第二行数据,现在有用了!~
SELECT colxml.query('
declare namespace p1="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
/p1:Record/p1:Exception') 
FROM #XMLTab
技术分享

--	条件查询用,如果在 exist() 方法中指定 true() 或 false() 函数,则总是返回 1
SELECT colxml FROM #XMLTab WHERE colxml.exist('true()')=1
SELECT colxml FROM #XMLTab WHERE colxml.exist('false()')=1


--	查看节点"/Record"的属性"@dt"日期是否为"2015-05-05"
--	元素中的属性转换为日志比较(也可以作为查询条件的判断)
--	参考构造函数:https://msdn.microsoft.com/zh-cn/library/ms189547.aspx
SELECT colxml 
,colxml.exist('/Record[(@dt cast as xs:date?) eq xs:date("2015-05-05")]')
,colxml.exist('/Record[(@dt cast as xs:date?) eq xs:date("2015-05-10")]')
FROM #XMLTab 
技术分享
--	文本判断:"/Record/Exception/Error"中的文本,只要其中一个符合就返回"1"
SELECT colxml 
,colxml.exist('/Record/Exception/Error[(text()[1] cast as xs:string ?) = xs:string("9003") ]')
,colxml.exist('/Record/Exception/Error[(text()[1] cast as xs:string ?) = xs:string("8008") ]')
,colxml.exist('/Record/Exception[1]/Error[(text()[1] cast as xs:string ?) = xs:string("9003") ]')
,colxml.exist('/Record/Exception[2]/Error[(text()[1] cast as xs:string ?) = xs:string("8008") ]')
FROM #XMLTab 
技术分享
--	带前缀的查询方法
SELECT colxml 
,colxml.exist('
	declare namespace p1="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
	/p1:Record/p1:Exception/p1:Error[(text()[1] cast as xs:string ?) = xs:string("9003") ]')
,colxml.exist('
	declare namespace p1="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
	/p1:Record/p1:Exception/p1:Error[(text()[1] cast as xs:string ?) = xs:string("8008") ]')
,colxml.exist('
	declare namespace p1="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
	/p1:Record/p1:Exception[1]/p1:Error[(text()[1] cast as xs:string ?) = xs:string("9003") ]')
,colxml.exist('
	declare namespace p1="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
	/p1:Record/p1:Exception[2]/p1:Error[(text()[1] cast as xs:string ?) = xs:string("8008") ]')
FROM #XMLTab 

--	还可以简写为:
WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' AS p1)
SELECT colxml 
,colxml.exist('/p1:Record/p1:Exception/p1:Error[(text()[1] cast as xs:string ?) = xs:string("9003") ]')
,colxml.exist('/p1:Record/p1:Exception/p1:Error[(text()[1] cast as xs:string ?) = xs:string("8008") ]')
,colxml.exist('/p1:Record/p1:Exception[1]/p1:Error[(text()[1] cast as xs:string ?) = xs:string("9003") ]')
,colxml.exist('/p1:Record/p1:Exception[2]/p1:Error[(text()[1] cast as xs:string ?) = xs:string("8008") ]')
FROM #XMLTab 



--	元素判断:元素中的其他元素是否存在.为1则是该节点中不包含的.
SELECT colxml 
,colxml.exist('/Record/Exception[1][not(Other)]') --1:元素"Exception[1]"不包含元素"Other"
,colxml.exist('/Record/Exception[2][not(Other)]') --0:元素"Exception[2]"包含元素"Other"
,colxml.exist('
	declare namespace p1="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
	/p1:Record/p1:Exception[1][not(p1:Other)]')  --1:元素"p1:Exception[1]"不包含元素"p1:Other"
,colxml.exist('
	declare namespace p1="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
	/p1:Record/p1:Exception[2][not(p1:Other)]')  --0:元素"p1:Exception[2]"包含元素"p1:Other"
FROM #XMLTab 
技术分享


--	使用"value"查询属性值和元素文本值
SELECT 
 colxml.value('(/Record/Exception/Task/@address)[1]','varchar(100)') AS [address1]
,colxml.value('(/Record/Exception[2]/Task/@address)[1]','varchar(100)') AS [address2]
,colxml.value('data(/Record/Exception[1]/Error)[1]','int') AS [Error1] 
,colxml.value('data(/Record/Exception[2]/Error)[1]','int') AS [Error2]  
,colxml.value('
	declare namespace p1="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
	data(/p1:Record/p1:Exception[2]/p1:Error)[1]
	','int') AS [p1:Error2] 
FROM #XMLTab 
技术分享

--	使用"query"查询属性值
SELECT   
 CONVERT(NVARCHAR(100),colxml.query('data(/Record/@dt)')) AS [id]  
,CONVERT(NVARCHAR(100),colxml.query('data(/Record/Exception/@type)[1]')) AS [type1] 
,CONVERT(NVARCHAR(100),colxml.query('data(/Record/Exception/@type)[2]')) AS [type2]  
,CONVERT(NVARCHAR(100),colxml.query('data(/Record/Exception[2]/@type)[1]')) AS [type2]
,CONVERT(NVARCHAR(100),colxml.query('data(/Record/Exception/@type)')) AS [type1 type2]
FROM #XMLTab
技术分享


--	可以当做查询条件:
SELECT * FROM #XMLTab WHERE CONVERT(NVARCHAR(100),colxml.query('data(/Record/@dt)'))='2015-05-05'


--	使用"nodes"中"value"查询属性值和元素文本值
SELECT node.c1.query('data(/Record/@dt)')
,CONVERT(NVARCHAR(100),colxml.query('data(/Record/@dt)')) AS [id] 
,node.c1.value('(@dt)','VARCHAR(50)') AS [id] 
,node.c1.value('(@dt)[1]','VARCHAR(50)') AS [id] 
,node.c1.value('(Exception/@type)[1]','VARCHAR(50)') AS [type1]  
,node.c1.value('(Exception/Error)[1]','VARCHAR(50)') AS [Error1]  
FROM #XMLTab
CROSS APPLY colxml.nodes('/Record') as node(c1)
技术分享


好了!~21图,测试到这。

XML类型的DML操作开始并不好记,看来只有多写语句才能记得。而这只是XML相关操作中很小的一部分。XML还涉及有类型化和非类型化的XML、XML类型导入导出、XML索引(主索引/辅索引/全文索引)、FOR XML的使用、XML架构集合等。太多!~有待学习!




郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。