使用FOR XML AUTO控制XML输出

日期: 2010-01-28 作者:朱祁林 来源:TechTarget中国 英文

  这篇文章描述如何通过使用FOR XML AUTO更好的控制XML输出格式。例如添加XML标记。用这个来替代难于理解的FOR XML EXPLICIT 语句。如果你在应用程序中即将反序列化输出的XML,你就会觉得这个信息对你有用。

  在For XML从句中,您通常使用下列方式之一:

  RAW

  AUTO

  EXPLICIT

  PATH

  如果你想完全掌控产生的XML,可以使用FOR XML EXPLICIT。但是它理解起来相当的困难,后面还要维护复杂的select语句。FOR XML AUTO 能产生最可读的SELECT语句,但是它也有缺点,不容易控制生成的XML。但使用一些技巧,例如通过使用额外的PATH选项,你可以做一些超过你预期的事情。RAW选项是很少使用,因此不讨论。PATH 选项允许您很容易地混合属性和元素。现在,让我们来使用FOR XML AUTO。

  在这个例子中,我们使用的是1:N关系的两个简单的数据表。一个表(SalesOrder)包含客户信息的订单,例外一张表(Items)中包含的具体的项。一个订单可以有多个项,一个项往往只属于一个订单。

  

  以最容易的开始。

  SELECT * FROM salesorder

  产生:

  ordernumber customername customerstreet

  ———– ———— ————–

  1 parker first av

  2 lesley sec av

  如果你想要使结果集是XML,我们添加FOR XML AUTO 语句:

  SELECT * FROM salesorder FOR XML AUTO

  它产生:

  <salesorder ordernumber=”1″ customername=”parker” customerstreet=”first av”/>
        <salesorder ordernumber=”2″ customername=”lesley” customerstreet=”sec av”/>

  

  现在,字段是作属性的,大多数情况下希望他们是元素。为了做到这点,添加ELEMENTS 参数

  SELECT * FROM salesorder FOR XML AUTO, ELEMENTS

  它产生:

        <salesorder>
            <ordernumber>1</ordernumber>
            <customername>parker</customername>
         </salesorder>

  如果你想要更改’salesorder’ 标签,使用:

  SELECT * FROM salesorder AS niceorder FOR XML AUTO, ELEMENTS

  它产生:

        <niceorder>
    <ordernumber>1</ordernumber>
    <customername>parker</customername>
       </niceorder>

  当然,这一招也适用的列名:

  SELECT ordernumber AS order_no FROM salesorder WHERE ordernumber = 1 FOR XML AUTO, ELEMENTS

  它产生:

  <salesorder>
    <order_no>1</order_no >
         </salesorder>

  如果你想添加其他标签或节点?例如,对有关客户信息添加’customer”标记?但对FOR XML AUTO来说,被证明是很困难的事件。一个可能的解决方案是使用SELF JOIN (join相同的表),但我找到一个更容易办法。经过一番摆弄和修订,我们使用子查询和有点滥用FOR XML PATH命令。

  代码

  SELECT
  ordernumber,
  (SELECT customername ,
  customerstreet FOR XML PATH(”),
  TYPE, ELEMENTS)
  as customer
  FROM
  salesorder
  FOR XML AUTO, ELEMENTS

  它产生:

  代码
  <salesorder>
    <ordernumber>1</ordernumber>
    <customer>
        <customername>parker</customername>
        <customerstreet>first av</customerstreet>
    </customer>
</salesorder>
<salesorder>
    <ordernumber>2</ordernumber>
    <customer>
        <customername>lesley</customername>
        <customerstreet>sec av</customerstreet>
    </customer>
</salesorder>

  注意使用附加的’TYPE’参数。这将确保子查询的结果将返回的是一个XML类型 (作为整个XML类型的结果的一部分),而不是NVARCHAR(MAX)类型。如果您要对整个结果添加外围标签,也是简单的小把戏:

  SELECT(
  SELECT
  customername
  FROM
  salesorder
  FOR XML AUTO, TYPE, ELEMENTS
  ) AS orderrequest FOR XML PATH(”), TYPE, ELEMENTS

  它产生:

<orderrequest>
    <salesorder>
        <customername>parker</customername>
    </salesorder>
    <salesorder>
        <customername>lesley</customername>
    </salesorder>
</orderrequest>

  为什么我们在子查询中不使用FOR XML AUTO?试试,它会产生一个错误。当子查询是查询一个实际的表时,您才能使用FOR XML AUTO(上述显然不是)。

  如果您想对所生产的XML完全控制,子查询是条出路。比方说,我们希望,每个订单,客户的名字和所有的项都属于订单。为此,您使用这样的相关子查询:

  SELECT
  customername ,
  (SELECT * FROM item WHERE item.ordernumber =
  salesorder.ordernumber FOR XML AUTO, TYPE, ELEMENTS)
  FROM
  salesorder
  FOR XML AUTO, ELEMENTS

  它产生:

  代码

</salesorder><salesorder>
    <customername>parker</customername>
    <item>
        <itemnumber>10</itemnumber>
        <description>pen</description>
        <ordernumber>1</ordernumber>
    </item>
    <item>
        <itemnumber>11</itemnumber>
        <description>paper</description>
        <ordernumber>1</ordernumber>
    </item>
</salesorder>

  当使用关联子查询,你可以使用规则的FOR XML AUTO, TYPE, ELEMENTS 语句。如果你想要在’items’外围有一个标签,只需在子查询后添加as,例如:

  

   SELECT
  customername ,
  (SELECT * FROM item WHERE item.ordernumber =
  salesorder.ordernumber FOR XML AUTO, TYPE, ELEMENTS)
  AS orderitems
  FROM
  salesorder
  FOR XML AUTO, ELEMENTS
  它产生:

        <salesorder>
    <customername>parker</customername>
    <orderitems>
        <item>
            <itemnumber>10</itemnumber>
            <description>pen</description>
            <ordernumber>1</ordernumber>
        </item>
        <item>
            <itemnumber>11</itemnumber>
            <description>paper</description>
            <ordernumber>1</ordernumber>
        </item>
    </orderitems>
</salesorder>

  为什么我们不只是简单的连接item表和order表。这有时会导致不必要的和不可预测的情况,涉及到产生XML布局:

  例如:

  SELECT
  item.description,
  salesorder.customername
  FROM
  salesorder
  INNER JOIN item ON item.ordernumber = salesorder.ordernumber
  FOR XML AUTO, ELEMENTS

  会产生这样的垃圾:

  代码

        <item>
    <description>pen</description>
    <salesorder>
        <customername>parker</customername>
    </salesorder>
</item>
<item>
    <description>paper</description>
    <salesorder>
        <customername>parker</customername>
    </salesorder>
</item>

  此外,如果使用连接查询,你很难添加一个外围的标签。因此,对于大多数的控制,使用FOR XML AUTO和关联子查询。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

相关推荐

  • Oracle Hyperion 11.1.2.1 迁移特性与问题

    Oracle Hyperion 11.1.2.1包含可以简化移植的新工具,它们在很多情况下能够减少操作步骤。但还是有诸如Essbase Studio的一些问题必须在以后的版本中进行修复。

  • SQL Server 数据访问策略:CLR

    CLR在很大程度上解放了TSQL逻辑运算能力不足的问题,而且CLR拥有丰富的语言支持,C#,VB.NET等;在.Net Framework基础上,拥有复杂的过程逻辑和计算。

  • 在Oracle数据库中使用XML数据获取业务信息

    只需要通过从一个XML表中提取数据,我们就能发送XML格式化的采购订单给下游使用,这与需要更多转换步骤的多个关系型表才能实现形成明显对比。

  • 详解如何将关系型数据发布为XML

    抽取是通过使用XMLType视图实现的,本质上是物化为SQL执行的一个存储查询结果。XMLType视图允许文档为中心的应用程序把底层的关系结构查询为虚拟的XML文档。