sql server XML中value(),exists(),nodes()方法

本文详细介绍了XQuery中的value()、exist()和nodes()方法的使用技巧,并通过具体示例展示了如何利用这些方法来处理XML数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. /*------------------------------------------------------------------------------+   
  2. #| = : = : = : = : = : = : = : = : = : = : = : = : = : = : = : = : = : = : = :  |   
  3. #|{>/------------------------------------------------------------------------\<}|   
  4. #|: | Author     :    小爱                                                      |   
  5. #|: | Description:    XQuery的 value() 方法、 exist() 方法 和 nodes() 方法        |  
  6. #|: | SQL Version:    适用于 SQL 2005, SQL 2008 , SQL 2012                      |   
  7. #|: | Copyright  :    转载请注明出处。更多请访问:http://blog.csdn.net/beirut     |  
  8. #|: | Create Date:    2012-11-22                                                |  
  9. #|: | About Me   :    一个菜鸟dba                                               |  
  10. #|{>\------------------------------------------------------------------------/<}|   
  11. #| = : = : = : = : = : = : = : = : = : = : = : = : = : = : = : = : = : = : = :  |   
  12. #+-----------------------------------------------------------------------------*/   
  13. /*  
  14. T-SQL 支持用于查询 XML 数据类型的 XQuery 语言的子集。  
  15. 本章将分析XQuery的 value() 方法、 exist() 方法 和 nodes() 方法  
  16. */  
  17. ------------------------------value() 方法--------------------------------------  
  18. --value(XPath条件,数据类型):结果为指定的标量值类型; XPath条件结果必须唯一  
  19.   
  20.   
  21. DECLARE @x XML   
  22. SET @x='  
  23. <root>  
  24.   <rogue id="001">  
  25.     <hobo id="1">  
  26.       <name>彪</name>  
  27.       <nickname>阿彪</nickname>  
  28.       <type>流氓</type>  
  29.     </hobo>  
  30.   </rogue>  
  31.   <rogue id="002">  
  32.     <hobo id="2">  
  33.       <name>光辉</name>  
  34.       <nickname>二辉</nickname>  
  35.       <type>流氓</type>  
  36.     </hobo>  
  37.   </rogue>  
  38.   <rogue id="001">  
  39.     <hobo id="3">  
  40.       <name>小德</name>  
  41.       <nickname>小D</nickname>  
  42.       <type>臭流氓</type>  
  43.     </hobo>  
  44.   </rogue>  
  45. </root>'  
  46. --value() 方法从 XML 中检索 rogue 属性值。然后将该值分配给 int 变量。  
  47.   
  48. SELECT @x.value('(/root/rogue/@id)[1]','int')  
  49. --解析 hobo 中属性 id 为2 的所有元素值  
  50. SELECT @x.value('(/root/rogue[2]/hobo/@id)[1]','int')  
  51. , @x.value('(/root/rogue[2]/hobo/name)[1]','varchar(10)')  
  52. , @x.value('(/root/rogue[2]/hobo/nickname)[1]','varchar(10)')  
  53. , @x.value('(/root/rogue[2]/hobo/type)[1]','varchar(10)')  
  54.   
  55.   
  56.   
  57. ------------------------------exist() 方法--------------------------------------  
  58. --exist() 方法- 用来判断 XQuery 表达式返回的结果是否为空  
  59.   
  60. ----判断 hobo 中属性 id  的值 是否为空  
  61.   
  62. SELECT @x.exist('(/root/rogue/hobo/@id)[1]')  
  63. --判断指定节点值是否相等  
  64. DECLARE @xml XML ='<root><name>a</name></root>'  
  65. SELECT @xml.exist('(/root/name[text()[1]="a"])')  
  66.   
  67. --用 exist() 方法比较日期时,请注意下列事项:  
  68. --代码 cast as xs:date? 用于将值转换为 xs:date 类型,以进行比较。  
  69. --@Somedate 属性的值是非类型化的。比较时,此值将隐式转换为比较右侧的类型(xs:date 类型)。  
  70. --可以使用 xs:date() 构造函数,而不用 cast as xs:date()。  
  71. DECLARE @a XML  
  72. SET @a='<root Somedate = "2012-01-01Z"/>'  
  73. SELECT @a.exist('/root[(@Somedate cast as xs:date?) eq xs:date("2012-01-01")]')  
  74. --下面的示例与上一示例类似,不同之处在于它具有 <Somedate> 元素。  
  75. SET @a = '<Somedate>2002-01-01Z</Somedate>'  
  76. SELECT  @a.exist('/Somedate[(text()[1] cast as xs:date ?) = xs:date("2002-01-01") ]')  
  77.    
  78. DECLARE    @x1 XML  
  79. SELECT @x1 = '<Employee Number="1001" Name="Jacob"/>'  
  80.   
  81. DECLARE @att VARCHAR(20)  
  82. SELECT @att = 'Number'  
  83.   
  84. IF @x1.exist('/Employee/@*[local-name()=sql:variable("@att")]') = 1   
  85.     SELECT 'Exists' AS Result  
  86. ELSE  
  87.     SELECT 'Does not exist' AS Result  
  88.   
  89. ------------------------------nodes() 方法--------------------------------------  
  90. --语法   
  91. --nodes (XQuery) as Table(Column) 将一个 XQuery 表达式拆分成多行  
  92. --以便于拆分成关系数据  
  93.    
  94. --将 rogue 节点拆分成多行  
  95. SELECT T.c.query('.'AS result  
  96. FROM   @x.nodes('/root/rogue') T(c);  
  97.   
  98. --扩展 rogue 拆分成数据行  
  99. SELECT T.c.value('(@id)[1]','varchar(10)'AS id  
  100. ,T.c.value('(./hobo/name)[1]','varchar(10)'AS name  
  101. ,T.c.value('(./hobo/nickname)[1]','varchar(10)'AS nickname  
  102. ,T.c.value('(./hobo/type)[1]','varchar(10)'AS type  
  103. FROM   @x.nodes('/root/rogue') T(c);  
  104.   
  105. /**********************************************************  
  106. *  
  107. * value() 方法 nodes() 方法 exist() 方法的综合应用  
  108. *  
  109. **********************************************************/  
  110.   
  111. --1 像下面的脚本,结点下还会用结点的,就要用到 text()  
  112. DECLARE @xml XML=N'   
  113. <a/>   
  114. <b>b<c>c</c></b>';  
  115. SELECT @xml.value('(/b)[1]''varchar(10)'), @xml.value('(/b/text())[1]''varchar(10)')  
  116.   
  117. --2 对表中的 XML 数据进行解析, 节点下面有多个相同节点的 使用 CROSS APPLY 和 nodes() 方法解析  
  118. IF OBJECT_ID('tempdb..[#tb]'IS NOT NULL DROP TABLE [#tb]   
  119. CREATE TABLE [#tb]([id] INT,[name] XML)   
  120. INSERT [#tb]   
  121. SELECT 1,'<r><i>a</i><i>b</i></r>' UNION ALL   
  122. SELECT 2,'<r><i>b</i></r>' UNION ALL   
  123. SELECT 3,'<r><i>d</i></r>'   
  124. SELECT   
  125.         T.c.query('.'),   
  126.         T.c.value('.''sysname')   
  127. FROM [#tb] A   
  128.         CROSS APPLY A.name.nodes('/r/i') T(c)  
  129.           
  130. --3 利用xml 拆分字符串  
  131. DECLARE @s VARCHAR(100)='1,2,3,4,5,6'  
  132. SELECT t.c.value('.','int'AS col  from    
  133. (SELECT CAST('<x>'+REPLACE(@s,',','</x><x>')+'</x>' AS XML ).query('.'AS nameAS a  
  134. CROSS APPLY a.name.nodes('/x') T(c)  
  135.   
  136.   
  137. --4 取任意属性的属性值,这里引入了 sql:variable  
  138. DECLARE @xml XML  
  139. DECLARE @Price DECIMAL(18 , 2),   
  140.         @xmlPath VARCHAR(10)= 'Price2'  
  141. SET @xml='<row ProductID="1" Price1="111.00" Price2="222.00" Price3="333.00" Price4="444.00" Price5="555.00" Price6="666.00" Price7="777.00"/>'  
  142. SELECT  col.value('(@Price2)[1]' , 'varchar(80)')  
  143. FROM    @xml.nodes('/row') data(col)  
  144.   
  145. SELECT  @xml.value('(/row/@*[local-name()=sql:variable( "@xmlPath")])[1]' , 'DECIMAL(18,2)')   
  146.   
  147. SELECT  col.value('(@Price2)[1]' , 'varchar(80)')  
  148. FROM    @xml.nodes('/row') data(col)  
  149.   
  150. SELECT  col.value('(@*[local-name()=sql:variable("@xmlPath")])[1]' , 'varchar(80)')  
  151. FROM    @xml.nodes('/row') data(col)  
  152. --组合使用  
  153. DECLARE    @x1 XML  
  154. SELECT @x1 = '  
  155. <Employees Dept="IT">  
  156.   <Employee Number="1001" Name="Jacob"/>  
  157.   <Employee Number="1002" Name="Bob" ReportsTo="Steve"/>  
  158. </Employees>'  
  159.   
  160. DECLARE @pos INT  
  161. SELECT @pos = 2  
  162.   
  163. SELECT  
  164.     @x1.value('local-name(  
  165.         (/Employees/Employee[2]/@*[position()=sql:variable("@pos")])[1]  
  166.     )','VARCHAR(20)') AS AttName  
  167.       
  168.   
  169. --5 使用 WITH XMLNAMESPACES  声明前缀 以及 XQuery 函数 namespace-uri()   
  170. DECLARE @xml XML  
  171. SELECT @xml = '  
  172. <employee  
  173. xmlns="http://schemas.microsoft.com/sqlserver/emp"  
  174. xmlns:loc="http://schemas.microsoft.com/sqlserver/location"  
  175. name="Jacob" position="CTO"  
  176. loc:city="Ahmedabad" loc:state="Gujarat" loc:country="India"  
  177. />'  
  178. --下面表达式将返回其命名空间 URI 为空的所有元素节点  
  179. --定义默认的命名空间  
  180. SELECT  
  181. x.value('local-name(.)''VARCHAR(20)'AS Attribute,  
  182. x.value('.''VARCHAR(20)'AS Value  
  183. FROM @xml.nodes('declare default element namespace "http://schemas.microsoft.com/sqlserver/emp";   
  184. /employee/@*[namespace-uri()=""]') a(x)  
  185. --or  直接用通用符  
  186.   
  187. SELECT  
  188. x.value('local-name(.)''VARCHAR(20)'AS Attribute,  
  189. x.value('.''VARCHAR(20)'AS Value  
  190. FROM @xml.nodes('/*/@*[namespace-uri()=""]') a(x)  
  191.   
  192. -- 使用 WITH XMLNAMESPACES  
  193. ;WITH XMLNAMESPACES(  
  194. DEFAULT 'http://schemas.microsoft.com/sqlserver/emp'  
  195. )  
  196. SELECT  
  197. x.value('local-name(.)''VARCHAR(20)'AS Attribute,  
  198. x.value('.''VARCHAR(20)'AS Value  
  199. FROM @xml.nodes('/employee/@*[namespace-uri()=""]') a(x)  
  200.   
  201. --返回所有带有前缀的节点  
  202. ;WITH XMLNAMESPACES(  
  203. DEFAULT 'http://schemas.microsoft.com/sqlserver/emp'  
  204. )  
  205. SELECT  
  206. x.value('local-name(.)''VARCHAR(20)'AS Attribute,  
  207. x.value('.''VARCHAR(20)'AS Value  
  208. FROM @xml.nodes('/employee/@*[namespace-uri()="http://schemas.microsoft.com/sqlserver/location"]') a(x)  
  209.   
  210. --返回所有带有前缀的节点个数统计  
  211. ;WITH XMLNAMESPACES(  
  212. DEFAULT 'http://schemas.microsoft.com/sqlserver/emp'  
  213. )  
  214. SELECT @xml.value('count(/employee/@*[namespace-uri()="http://schemas.microsoft.com/sqlserver/location"])''int'AS [count]  
  215.   
  216. --sql:column() 函数  
  217. --将普通数据列和 xml 数据列进行合并  
  218.   
  219.   
  220. DECLARE @t TABLE (id INT , data XML)  
  221.    
  222. INSERT  INTO @t (id , data)  
  223.         SELECT  1 , '<root><name>二辉</name><type>流氓</type></root>'  
  224.         UNION ALL  
  225.         SELECT  2 , '<root><name>彪</name><type>流氓</type></root>'  
  226. SELECT  id ,   
  227. data=data.query('<root>  
  228.     <id>{sql:column("id")}</id>  
  229.     {/root/name}  
  230.     {/root/type}  
  231.     </root>')  
  232. FROM    @t  
  233.   
  234. /*  
  235.   
  236. id          data  
  237. ----------- ----------------------------------------------------  
  238. 1   <root><id>1</id><name>二辉</name><type>流氓</type></root>  
  239. 2   <root><id>2</id><name>彪</name><type>流氓</type></root>  
  240.   
  241. */  
  242.   
  243. --根据一个xml 变量 与表中的值进行关联查询  
  244.   
  245. DECLARE @tb TABLE (id INT)  
  246. INSERT INTO @tb(id)   
  247. SELECT 1 UNION ALL   
  248. SELECT 2 UNION ALL   
  249. SELECT 3  
  250.   
  251. declare @XmlData xml   
  252. set  @XmlData = '  
  253. <root>  
  254. <rogue><typeid>1</typeid><name>二辉</name><type>流氓</type></rogue>  
  255. <rogue><typeid>2</typeid><name>彪</name><type>流氓</type></rogue>  
  256. </root>'  
  257.   
  258. SELECT t.id AS id  
  259. FROM @tb t  
  260. CROSS APPLY @XmlData.nodes('/root/rogue/typeid[. = sql:column("id")]') a(x)  
  261.   
  262.   
  263.   
  264. --string-length() 函数 和 number() 函数  
  265. --提取长度为5的数字  
  266. DECLARE @t TABLE (CustomerID INT, CustomerAddress VARCHAR(50))  
  267. INSERT INTO @t(CustomerID, CustomerAddress)   
  268.     SELECT 1, '12 20 97TH STREET NEW GARDENS, NY  11415  APT 8P' UNION ALL  
  269.     SELECT 2, '20-10 93RD STREET #8A VICTORIA NY 11106 19TH FLR' UNION ALL  
  270.     SELECT 3, '290 BERKELEY STREET APT24D  NYC, NY  10038' UNION ALL  
  271.     SELECT 4, '351-250  345 STREET PANAMA BEACH 11414  APT4F'  
  272.       
  273. ;WITH cte AS (  
  274.     SELECT   
  275.         CustomerID,  
  276.         CAST('<i>' +REPLACE(CustomerAddress, ' ''</i><i>') + '</i>' AS XML).query('.'AS CustomerAddress  
  277.     FROM @t  
  278. )  
  279. SELECT   
  280.     CustomerID,  
  281.     x.i.value('.''VARCHAR(10)'AS ZipCode  
  282. FROM cte  
  283. CROSS APPLY CustomerAddress.nodes('//i[string-length(.)=5][number()>0]') x(i)  
  284.       
  285. /*  
  286. CustomerID  ZipCode  
  287. ----------- ----------  
  288. 1           11415  
  289. 2           11106  
  290. 3           10038  
  291. 4           11414  
  292. */  
  293.   
  294. --使用 contains() 函数进行模糊查询  
  295. SELECT  a.x.value('name[1]' , 'varchar(10)')  
  296. FROM    @x.nodes('/root/rogue/hobo') a (x)  
  297. CROSS APPLY a.x.nodes('type[contains(.,"臭流氓")]') b (y)  
  298.   
  299. SELECT  t.c.query('.')  
  300. FROM    @x.nodes('/root/rogue/hobo[./type[contains(.,"臭流氓")]]') t (c)  
--本篇文章转自: Beirut的专栏
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值