大部分情况下,我们使用的xml有着明确的定义结构,该啥节点,该啥属性,该啥层级,基本在设计之初就已经确定了,很少有确定了结构的xml格式再后续使用中改变结构,所以,通常情况下,我们都可以根据已有的结构来直接获取或查询数据
而sqlserver自2005版起,就对xml类型的数据进行了支持,且直接提供了5种操作,query()、value()、exist()、nodes()和modify(),有兴趣的同学可以到msdn中Microsoft SQL Server 2005 中的 XML 支持一文查看更多内容,包括xquery相关的部分,毕竟不是完整的xpath嘛,还是要看一下的。
然后,就是根据一个固定的xml文档,来作为演示依据了,xml文档如下:
<r>
<summary>
<title val="宁夏大学文献信息资源保障与服务提升建设数据库采购项目" />
<cls val="服务/信息技术服务/其他信息技术服务,服务/信息技术服务/其他信息技术服务,服务/信息技术服务/其他信息技术服务" />
<org val="宁夏大学" />
<city val="宁夏回族自治区" />
<publish_time val="2022年04月12日 09:54" />
<expert val="陈玉春(组长)、王维友、马勇、马文杰" />
<final_credit val="¥227.870000 万元(人民币)" />
<contact val="张莹" />
<contact_phone val="0951-5969335" />
<org_address val="宁夏银川市西夏区贺兰山西路489号" />
<org_phone val="09512061502" />
<agency val="宁夏恒盛招标有限公司" />
<agency_address val="宁夏银川市金凤区泰康街隆基商务大厦10楼" />
<agency_phone val="0951-5969335" />
</summary>
<result>
<url val="http://www.ccgp.gov.cn/cggg/dfgg/zbgg/202204/t20220412_17760138.htm" />
<type val="中标公告" />
<title val="宁夏大学文献信息资源保障与服务提升建设数据库采购项目中标公告" />
<category>
<main>
<ca id="2493" val="数据库" />
</main>
<more>
<ca id="2110" val="pad" />
<ca id="2493" val="数据库" />
</more>
</category>
<SN val="HSZB-2022ZC022">
<row name="项目编号" val="HSZB-2022ZC022" />
<row name="项目编号" val="HSZB-2022ZC022" />
<row name="采购编号" val="2022NCZ000812" />
</SN>
<budget />
<purchaser>
<org val="宁夏大学" />
<org_addr val="宁夏银川市西夏区贺兰山西路489号" />
<org_phone val="09512061502" />
<agency val="宁夏恒盛招标有限公司" />
<agency_addr val="宁夏银川市金凤区泰康街隆基商务大厦10楼" />
<agency_phone val="" />
</purchaser>
<date val="2022-04-12 09:54:00">
<row val="2022年04月13" pos="620" isDate="true" />
<row val="2022-04-12" pos="932" name="宁夏恒盛招标有限公司发布日期" isDate="true" />
</date>
<result>
<package>
<row>
<mode name="方式" val="表格" />
<company name="中标单位" val="北京华宇星航国际教育科技有限公司" />
<credit name="中标金额" val="1209500.00" />
</row>
<row>
<mode name="方式" val="表格" />
<company name="中标单位" val="山东数盟网络科技有限公司" />
<credit name="中标金额" val="564200.00" />
</row>
<row>
<mode name="方式" val="表格" />
<company name="中标单位" val="北京智诚阅品文化传播有限公司" />
<credit name="中标金额" val="505000.00" />
</row>
</package>
</result>
</result>
</r>
因为只是为了学习一下几种操作方法,所以,咱们就不用数据库里的内容了,直接 declare @xml xml然后set @xml = ‘上边的xml文档内容’
在介绍这些方法之前,先声明一下,别看各个指令里的内容都是字符串,但是,这里要说但是,他不支持字符串拼接!如果你想用变量代替到指令里,需要用sql:variable(“@变量名”)来代替!
1、exist(),节点是否存在
select @xml.exist('//*')
select @xml.exist('//r')
select @xml.exist('//line')
xquery、xpath语法这里就不讲了,有兴趣的同学自行百度
2、value(),取值
select @xml.value('(//org/@val)[1]','nvarchar(50)')
select @xml.value('(//credit/@val)[1]','nvarchar(50)')
select @xml.value('.','nvarchar(max)')
3、nodes(),获取节点集合
select T.c.value('local-name(.)','varchar(50)') node
,T.c.value('./@name[1]','nvarchar(max)') name
,T.c.value('./@val[1]','nvarchar(max)') val
from @xml.nodes('//*') T(c)
select T.c.value('local-name(.)','varchar(50)') node
,T.c.value('./@name[1]','nvarchar(max)') name
,T.c.value('./@val[1]','nvarchar(max)') val
from @xml.nodes('//*[@val > 550000]') T(c)
4、query(),查询,用xquery语法进行查询,这个就比较复杂了,这里只做两个简单的例子
select @xml.query('count(//credit)').value('.','int')
,@xml.query('count(//credit[@val>550000])').value('.','int')
,@xml.query('count(//*)').value('.','int')
select @xml.query('
for $i in //credit
let $val := $i/@val
where $val > 550000
order by (number($val))[1]
return <credit>{$val}</credit>
')
<credit val="564200.00" />
<credit val="1209500.00" />
总之,query很好用,但想用好query,xquery语法一定要懂,xslt最好也了解一点,xpath最好也了解一点,反正是挺迷得,老顾平时基本上不怎么用这个
5、modify(),动态修改xml文档内信息
。。。。。。。 。。。。。。。 老顾完全完全不推荐用这个玩意去修改xml数据,太繁琐了,什么增加、删除节点啦,什么增加、删除、修改属性啦,完完全全都是通过这一个方法实现的,而这个方法里有自己的指令集!需要使用 XML 数据操作语言 (DML) 中的字符串,又一个扩展的知识点!
算了,偷个懒,modify自行百度,这里就不介绍了,真要有同学需要,咱们再另起篇章好了。
|