• SQL Server : FOR XML PATH 函数用法以及转义字符正常显示


    简介For XML PATH

    For XML,就是将查询结果作为XML来检索。

    XML有4中模式,官方文档上有这4种模式的使用方法。

    模式
    描述
    RAW  SELECT 语句返回的行集中为每个行生成一 <个行> 元素
    AUTO 将基于指定 SELECT 语句的方式来使用试探性方法在 XML 结果中生成嵌套。(说的是什么?是能够生成嵌套的XML吗?)
    EXPICIT  模式允许对 XML 的形状进行更多控制。
    PATH  任务比较简单的方式。

    仅当执行设置了这些模式的查询时,这些模式才有效。 它们不会影响以后执行的任何查询的结果。

    接下来我们只讲Path模式(事实上,我在网上看到最多的也是PATH模式的例子)

    很多问题等遇上了,再说,先说说FOR XML PATH的基本用法。

    假设有一张兴趣爱好表(t_bd_hobby),表内容如下:

    接下来,我们执行FOR XML语句:

    SELECT *
    FROM dbo.t_bd_hobby
    FOR XML PATH

    返回结果如下

     1 <row>
     2   <ID>1</ID>
     3   <hobby>爬山</hobby>
     4 </row>
     5 <row>
     6   <ID>2</ID>
     7   <hobby>游泳</hobby>
     8 </row>
     9 <row>
    10   <ID>3</ID>
    11   <hobby>美食</hobby>
    12 </row>

    因此,FOR XML PATH可以将查询结果依据行输出成XML格式。

    自定义节点名称

    如何改变节点的名称呢?

    SELECT *
    FROM dbo.t_bd_hobby
    FOR XML PATH('Myhobby')

    输出的XML如下:

     1 <Myhobby>
     2   <ID>1</ID>
     3   <hobby>爬山</hobby>
     4 </Myhobby>
     5 <Myhobby>
     6   <ID>2</ID>
     7   <hobby>游泳</hobby>
     8 </Myhobby>
     9 <Myhobby>
    10   <ID>3</ID>
    11   <hobby>美食</hobby>
    12 </Myhobby>

     自定义列名称

    当然,我们也可以自定义列名称。

    SELECT ID AS 编码, hobby AS 兴趣
    FROM dbo.t_bd_hobby
    FOR XML PATH

     输出的XML如下:

     1 <row>
     2   <编码>1</编码>
     3   <兴趣>爬山</兴趣>
     4 </row>
     5 <row>
     6   <编码>2</编码>
     7   <兴趣>游泳</兴趣>
     8 </row>
     9 <row>
    10   <编码>3</编码>
    11   <兴趣>美食</兴趣>
    12 </row>

    For XML Path的应用场景——多行转一行

    既然节点和列都可以被自定义,那么我们是不是可以构建我们喜欢的输出方式呢?

    SELECT '[ '+hobby+' ]' FROM t_bd_hobby FOR XML PATH('')

    输出如下:

    [ 游泳 ][ 爬山 ][ 美食 ]

    可以改成用逗号分割

    SELECT ',' + hobby FROM t_bd_hobby FOR XML PATH('')

    这样,多行合并为一行,每个字段用逗号隔开。

    ,游泳,爬山,美食,

    有没有一个函数截取字符串,把前面一个逗号去掉?这样就可以转换为我们常见的形式。stuff就是这么用的。

    SELECT stuff( ( SELECT ',' + hobby FROM t_bd_hobby FOR XML PATH('')) ,1,1 ,'')

    输出结果如下:

    游泳,爬山,美食

    For XML Path的应用场景——分组的多行转一行

    既然我们能够将多行合并为一行,那么我们能不能完成如下功能。首先有一张学生表,数据如下:

     我们要以名字为列,将爱好按逗号隔开,如下所示:

     该如何做呢?执行语句的总体思想如下:

    1. 按照fname分类。所以使用grou by语句。

    2、使用上文已知的字符串截取方法,将fhobby视为被分组的聚合函数,这里先用1表示。

    SELECT fname , '1' AS hobby
    FROM tb_personhobbys
    GROUP BY fname

    显示结果如下:

    3.没问题后,我们将'1'替换为for xml path的多行转一行的形式。

    1 SELECT fname , (STUFF(( SELECT + ',' + fhobby    FROM tb_personhobbys     FOR XML PATH('')) ,1,1, '' ))  AS hobby
    2 FROM tb_personhobbys
    3 GROUP BY fname

    这样的结果,将所有的hobby都传达进来了。

     显然不是我们想要的结果,能将hobby局行列传递条件吗?当然可以。

    3. 聚合列内传递fname条件。这里,为了区分,需要给外面的表(tb_personhobbys)命名。

    1 SELECT fname , (STUFF(( SELECT + ',' + fhobby    FROM tb_personhobbys  WHERE fname = a.fname    FOR XML PATH('')) ,1,1, '' ))  AS hobby
    2 FROM tb_personhobbys a
    3 GROUP BY fname

    这样,我们就完成了分组的多行转一行了。

    参考网址

  • 相关阅读:
    windows service 安装和卸载指令
    jackson 进行json与java对象转换 之四
    jackson 进行json与java对象转换 之三
    jackson 进行json与java对象转换 之二
    jackson 进行json与java对象转换 之一
    jackson2.x与Jackson1.9的比较
    判断Integer值相等不能用==
    java:String使用equals和==比较的区别
    Java中自定义枚举(Enum)项的值,可设置为指定的值
    Java enum(枚举)使用详解之四
  • 原文地址:https://www.cnblogs.com/luyj00436/p/16496515.html
Copyright © 2020-2023  润新知