用RAW模式查询创建XML(SQL Server 与 XML 笔记)

来源:互联网 发布:淘宝开个店铺多少钱 编辑:程序博客网 时间:2024/06/07 20:16

在开发过程中,会遇到提取关系数据并返回给客户端时需将其格式化为XML的情况,SQL Server通过叫做For xml的T-SQL子句支持该功能,呵呵,多么幸运!

RAW模式是最简单的xml输出格式。假设有如下数据:

DECLARE @T1 table(UserID int , UserName nvarchar(50),CityName nvarchar(50));insert into @T1 (UserID,UserName,CityName) values (1,null,'上海')insert into @T1 (UserID,UserName,CityName) values (2,'b','北京')insert into @T1 (UserID,UserName,CityName) values (3,'c','上海')insert into @T1 (UserID,UserName,CityName) values (4,'d','北京')insert into @T1 (UserID,UserName,CityName) values (5,'e','上海')
1、使用RAW模式:

现有一条SQL就可以将其变为一个xml字符串:

/*列做为属性名存在行标签为row的元素中*/select * from @T1 for xml raw
查询出来的结果如下:
<row UserID="1" CityName="上海" /><row UserID="2" UserName="b" CityName="北京" /><row UserID="3" UserName="c" CityName="上海" /><row UserID="4" UserName="d" CityName="北京" /><row UserID="5" UserName="e" CityName="上海" />

2、ELEMENTS 与 XSINL条件的应用

我们可以看到1中输出的xml的格式并非良好,并且userid为1 的那行元素丢失了UserName属性。

首先给行(row)与列标签自定义别名,具体SQL如下:

/*可以对列属性起别名,并对原行标签为row的元素起别名(person),放在根元素为(persons)下*/select UserID id,UserName name,CityName cityfrom @T1 for xml raw('person'),root('persons') ;
输出结果如下:
<persons>  <person id="1" city="上海" />  <person id="2" name="b" city="北京" />  <person id="3" name="c" city="上海" />  <person id="4" name="d" city="北京" />  <person id="5" name="e" city="上海" /></persons>
这样就加入了根元素(persons)及行元素(person)的标签名称。

如何将行元素的属性变为其子元素呢?

即变成这个样子:

<persons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">  <person>    <id>1</id>    <name xsi:nil="true" />    <city>上海</city>  </person>  <person>    <id>2</id>    <name>b</name>    <city>北京</city>  </person>  <person>    <id>3</id>    <name>c</name>    <city>上海</city>  </person>  <person>    <id>4</id>    <name>d</name>    <city>北京</city>  </person>  <person>    <id>5</id>    <name>e</name>    <city>上海</city>  </person></persons>
呵呵 有了ELEMENTS条件就容易多了,再加上XSINIL条件给力地将userid为1 的person属性Name补全了:
/*在子句中加入 elements条件,查询将返回元素而不是属性;  将XSINIL条件与Elements条件一起使用可以解决列值为空时导致该元素标签缺失问题*/select UserID id,UserName name,CityName cityfrom @T1 for xml raw('person'),root('persons'),elements xsinil
这样一个完整的结构良好的xml输出结果就有了。

3、加入明确的命名空间

可以在xml中包含一个生成架构。

在For XML子句中使用 XMLSCHEMA条件会产生带有明确目标命名空间的架构。

select UserID id,UserName name,CityName cityfrom @T1 for xml raw('person'),root('persons'),elements xsinil,xmlschema
输出如下:
<persons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">  <xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">    <xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />    <xsd:element name="person">      <xsd:complexType>        <xsd:sequence>          <xsd:element name="id" type="sqltypes:int" nillable="1" />          <xsd:element name="name" nillable="1">            <xsd:simpleType>              <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="2052" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth">                <xsd:maxLength value="50" />              </xsd:restriction>            </xsd:simpleType>          </xsd:element>          <xsd:element name="city" nillable="1">            <xsd:simpleType>              <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="2052" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth">                <xsd:maxLength value="50" />              </xsd:restriction>            </xsd:simpleType>          </xsd:element>        </xsd:sequence>      </xsd:complexType>    </xsd:element>  </xsd:schema>  <person xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">    <id>1</id>    <name xsi:nil="true" />    <city>上海</city>  </person>  <person xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">    <id>2</id>    <name>b</name>    <city>北京</city>  </person>  <person xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">    <id>3</id>    <name>c</name>    <city>上海</city>  </person>  <person xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">    <id>4</id>    <name>d</name>    <city>北京</city>  </person>  <person xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">    <id>5</id>    <name>e</name>    <city>上海</city>  </person></persons>

如何自定义命名空间呢?可以使用XMLSHEMA(‘urn:sampleNamespace’)来定义自己的命名空间标识符。

select UserID id,UserName name,CityName cityfrom @T1 for xml raw('person'),root('persons'),elements xsinil,xmlschema('urn:mynamespace')
输出如下:
<persons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">  <xsd:schema targetNamespace="urn:mynamespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">    <xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />    <xsd:element name="person">      <xsd:complexType>        <xsd:sequence>          <xsd:element name="id" type="sqltypes:int" nillable="1" />          <xsd:element name="name" nillable="1">            <xsd:simpleType>              <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="2052" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth">                <xsd:maxLength value="50" />              </xsd:restriction>            </xsd:simpleType>          </xsd:element>          <xsd:element name="city" nillable="1">            <xsd:simpleType>              <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="2052" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth">                <xsd:maxLength value="50" />              </xsd:restriction>            </xsd:simpleType>          </xsd:element>        </xsd:sequence>      </xsd:complexType>    </xsd:element>  </xsd:schema>  <person xmlns="urn:mynamespace">    <id>1</id>    <name xsi:nil="true" />    <city>上海</city>  </person>  <person xmlns="urn:mynamespace">    <id>2</id>    <name>b</name>    <city>北京</city>  </person>  <person xmlns="urn:mynamespace">    <id>3</id>    <name>c</name>    <city>上海</city>  </person>  <person xmlns="urn:mynamespace">    <id>4</id>    <name>d</name>    <city>北京</city>  </person>  <person xmlns="urn:mynamespace">    <id>5</id>    <name>e</name>    <city>上海</city>  </person></persons>
SQL server将用该目标名称空间来标记数据流。当给实用工具(这些实用工具需要用于绑定的架构信息)返回数据时,该方法就显得非常有用。


原创粉丝点击