zoukankan      html  css  js  c++  java
  • (Sql Server)SQL FOR XML

    摘要:sql中的for xml语法为表转化为xml提供了很好的支持,当然使用同样的程序语言也能够达到同样的效果,但是有了for xml将使得这一切更加的方便。

    主要内容:

    Select 的查询结果会作为行集返回,但是你同样可以在sql中指定for xml子句使得查询作为xml来检索。在for xml子句中,可以指定以下模式之一:RAW 、AUTO、EXPLICIT和PATH。

    RAW模式返回行为元素,每一列的值作为元素的属性;AUTO模式返回表名为节点的元素,每一列的属性作为属性输出;EXPLICIT模式通过SELECT语法定义输出XML结构;PATH模式中列名或列别名作为XPATH表达式来处理。

    下面是四种方式输出的效果

    RAW模式

    SELECT TOP 5 ProductName,UnitPrice FROM dbo.Products FOR XML RAW

    查询结果

    <row ProductName="Chai" UnitPrice="18.0000" />
    <row ProductName="Chang" UnitPrice="19.0000" />
    <row ProductName="Aniseed Syrup" UnitPrice="10.0000" />
    <row ProductName="Chef Anton's Cajun Seasoning" UnitPrice="22.0000" />
    <row ProductName="Chef Anton's Gumbo Mix" UnitPrice="21.3500" />

    AUTO模式

    SELECT TOP 5 ProductName,UnitPrice FROM dbo.Products FOR XML AUTO

    查询结果

    <dbo.Products ProductName="Chai" UnitPrice="18.0000" />
    <dbo.Products ProductName="Chang" UnitPrice="19.0000" />
    <dbo.Products ProductName="Aniseed Syrup" UnitPrice="10.0000" />
    <dbo.Products ProductName="Chef Anton's Cajun Seasoning" UnitPrice="22.0000" />
    <dbo.Products ProductName="Chef Anton's Gumbo Mix" UnitPrice="21.3500" />

    EXPLICIT模式

    复制代码
    SELECT TOP 5 1 AS Tag,0 AS Parent, OrderID AS [Order!1!ID],OrderDate AS [Order!1!Date],CustomerID AS [Order!1!Customer],NULL AS [OrderDetail!2!ProductID],NULL AS [OrderDetail!2!UnitPrice],NULL AS [OrderDetail!2!Quantity] FROM dbo.Orders WHERE dbo.Orders.OrderID='10248'
    UNION ALL
    SELECT TOP 5 2 AS Tag,1 AS Parent, NULL,NULL ,NULL,ProductID,UnitPrice,Quantity FROM dbo.[Order Details] WHERE OrderID='10248'
    FOR XML EXPLICIT
    复制代码

    查询结果

    <Order ID="10248" Date="1996-07-04T00:00:00" Customer="VINET">
    <OrderDetail ProductID="11" UnitPrice="14.0000" Quantity="12" />
    <OrderDetail ProductID="42" UnitPrice="9.8000" Quantity="10" />
    <OrderDetail ProductID="72" UnitPrice="34.8000" Quantity="5" />
    </Order>

    PATH模式

    SELECT TOP 5 ProductName AS Name, UnitPrice AS Price FROM dbo.Products FOR XML PATH('Cmj')

    查询结果

    复制代码
    <Cmj>
    <Name>Chai</Name>
    <Price>18.0000</Price>
    </Cmj>
    <Cmj>
    <Name>Chang</Name>
    <Price>19.0000</Price>
    </Cmj>
    <Cmj>
    <Name>Aniseed Syrup</Name>
    <Price>10.0000</Price>
    </Cmj>
    <Cmj>
    <Name>Chef Anton's Cajun Seasoning</Name>
    <Price>22.0000</Price>
    </Cmj>
    <Cmj>
    <Name>Chef Anton's Gumbo Mix</Name>
    <Price>21.3500</Price>
    </Cmj>
    复制代码

    RAW模式和AUTO模式相对比较简单,灵活性当然也是比较差的。EXPLICIT模式会将查询执行生成的行集转换为XML文档,也就是说结构可以自定义,当然这必须符合一定的格式。就拿上面的语句来说:

    Tag指定生成节点的嵌套级别,列名必须为"Tag"例如上面的级别为1。

    Parent指定当前Tag的父级层次,列名必须为"Parent",NULL表示顶级。

    其他列名,例如[Order!1!ID]分别代表元素名称、Tag标记(也就是层级)、属性名称。例如上面的这一列就代表会在第一级节点中生成一个节点名称为Order的节点并且有一个属性ID。

    此外还需要指出的是这个列名还有一个可选部分,完整的形式是[ElementName!TagNumber!AttributeName!Directive],最后一部分Directive是可选的,如果不指定的话默认作为ElementName中的属性名称;当然如果制定了xml、cdata或者element那么它将作为ElementName的一个子元素而不是属性。并且指定了此选项之后AttributeName可以为空。

    上面的例子中如果去掉For XML EXPLICIT之后查询到的数据时如下形式:

    按照上面的规则不难看出,FOR XML EXPLICIT会按照顺序生成xml:

    第一次执行(第一行数据)时tag为1,parent为0,则此时会按照列名创建一个Order节点,并依次创建三个属性:ID、Date和Customer,其值为:10248、1996-07-04 00:00:00.000、VINET。此时不会生成ProductID属性,因为它的Tag为2,需要在第二级节点中创建,其他另个属性也是如此。

    第二次执行(第二行数据)时Tag为2,Parent为1,也就是要在Tag为1的节点中创建一个2级节点。然后根据查找列名中Tag为2的列,依次创建ProductID、UnitPrice、Quantity属性,并赋值。

    第三次、第四次同第二次执行类似,不同的只是数据而已。

    PATH模式应该说是使用率相当高的,原因比较简单,它的使用既简单又灵活。在PATH模式中,节点名称可以使列名也可以通过别名指定又或者根本不指定,不指定的情况下就只显示节点内数据;根节点可以指定也可以不指定,不指定情况下默认为"row",并且根节点指定为""的情况下可以完全取消根节点的显示。有了这一属性就可以使用PATH模式完成很多有用的操作。

    没有指定根节点时:

    SELECT TOP 5 ProductName FROM dbo.Products FOR XML PATH
    复制代码
    <row>
    <Name>Chai</Name>
    <Price>18.0000</Price>
    </row>
    <row>
    <Name>Chang</Name>
    <Price>19.0000</Price>
    </row>
    <row>
    <Name>Aniseed Syrup</Name>
    <Price>10.0000</Price>
    </row>
    <row>
    <Name>Chef Anton's Cajun Seasoning</Name>
    <Price>22.0000</Price>
    </row>
    <row>
    <Name>Chef Anton's Gumbo Mix</Name>
    <Price>21.3500</Price>
    </row>
    复制代码

    去掉根节点名称:

    SELECT TOP 5 ProductName FROM dbo.Products FOR XML PATH('')
    <ProductName>Alice Mutton</ProductName>
    <ProductName>Aniseed Syrup</ProductName>
    <ProductName>Boston Crab Meat</ProductName>
    <ProductName>Camembert Pierrot</ProductName>
    <ProductName>Carnarvon Tigers</ProductName>

    去掉根节点和子节点名称:

    SELECT TOP 5 ProductName+'' FROM dbo.Products FOR XML PATH('')
    Alice MuttonAniseed SyrupBoston Crab MeatCamembert PierrotCarnarvon Tigers

    可以发现去掉节点名称之后for xml path起到了字符串连接的作用,这样一来就可以利用这一特性完成字符串拼接,例如下面的语句就能完成可以将五种产品用","进行分割的功能:

    SELECT LEFT(ProductNames,(LEN(ProductNames)-1)) FROM(
    SELECT
    (SELECT TOP 5 ProductName+',' FROM dbo.Products FOR XML PATH('')) AS ProductNames
    ) AS T

    原文地址:崔江涛(KenshinCui)

  • 相关阅读:
    使用QOAuth来进行新浪/腾讯微博验证(二)
    很不错的Utility库,C#4扩展 各种功能齐全,两行代码搞定图片转字符
    使用QOAuth来进行新浪/腾讯微博验证(一)
    可怜的小猪&香农熵
    消息队列MQ如何保证消息不丢失
    40 亿个 QQ 号码如何去重,bitmap去重
    参数的设置
    自动化测试的十个要点
    LR学习中的一个低级错误
    Windows下用CMake编译libuv
  • 原文地址:https://www.cnblogs.com/littlewu/p/6117650.html
Copyright © 2011-2022 走看看