• FOR XML之RAW模式


    描述:

    raw模式将查询结果集中的每一行转换为带有<row>元素名称的xml元素,将每一行的列转换为row的属性.

    可以通过编写嵌套FOR XML查询来生成XML层次结构

    在默认情况下,所有非null值都将被映射为<row>元素的属性.

    如果需要将查询结果集中数据转换为<row>元素的子元素,需要使用elements指令.

    语法:

    FOR XML
    RAW [ ('ElementName') ] 
        [ 
           <CommonDirectives> 
           [ , { XMLDATA | XMLSCHEMA [ ('TargetNameSpaceURI') ]} ] 
           [ , ELEMENTS [ XSINIL | ABSENT ] 
        ]
     <CommonDirectives> ::= 
       [ , BINARY BASE64 ]
       [ , TYPE ]
       [ , ROOT [ ('RootName') ] ]

    具体参见例子:

    建表Base,表结构如下:

    列名 数据类型 允许空
    id int 允许
    body nvarchar(50) 允许

    插入表数据如下:

    id body
    1 aaaa
    2 bbbb
    3 cccc
    4  

    例句:

    A.返回查询数据的信息,使用for xml raw 模式

    /*
    结果:
        <row id="1" body="aaaa" />
        <row id="2" body="bbbb" />
        <row id="3" body="dddd" />
        <row id="4" />
    */
    select * from base for xml raw;

    通过指定ELEMENTS指令使结果集以子元素的形式出现.

    /*
    结果:
        <row>
          <id>1</id>
          <body>aaaa</body>
        </row>
        <row>
          <id>2</id>
          <body>bbbb</body>
        </row>
        <row>
          <id>3</id>
          <body>dddd</body>
        </row>
        <row>
          <id>4</id>
        </row>
    */
    select * from base for xml raw,elements;

    我们注意到这个例句中没有将id为4的body显示出现.

    原因是因为,在使用elements指令时,如果没有指定后面的命令,则默认使用abscent,此时不会为null值创建任何元素.

    在下面的例句中通过使用elements xsinil可使null值显示在xml中.

    B.同时指定elements指令和xsinil指令以生产null列值的元素

    /*
    结果:
        <row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <id>1</id>
          <body>aaaa</body>
        </row>
        <row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <id>2</id>
          <body>bbbb</body>
        </row>
        <row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <id>3</id>
          <body>dddd</body>
        </row>
        <row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <id>4</id>
          <body xsi:nil="true" />
        </row>
    */
    select * from base for xml raw,elements xsinil;

    对于每条数据都是以<row>元素显示会让人看起来很不舒服,如何修改<row>元素名称为其他名称呢.

    C.重命名<row>元素

    /*
    结果:
        <baseinfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <id>1</id>
          <body>aaaa</body>
        </baseinfo>
        <baseinfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <id>2</id>
          <body>bbbb</body>
        </baseinfo>
        <baseinfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <id>3</id>
          <body>dddd</body>
        </baseinfo>
        <baseinfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <id>4</id>
          <body xsi:nil="true" />
        </baseinfo>
    */
    select * from base for xml raw('baseinfo'),elements xsinil;

    我们都知道,每个xml文件都有一个根元素,我们如何为这段xml文本加上它的根元素呢.

    D.为for xml生成的xml指定根元素

    可使用root指定,root指令的默认根元素为<root>

    /*
    结果:
        <base xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <baseinfo>
            <id>1</id>
            <body>aaaa</body>
          </baseinfo>
          <baseinfo>
            <id>2</id>
            <body>bbbb</body>
          </baseinfo>
          <baseinfo>
            <id>3</id>
            <body>dddd</body>
          </baseinfo>
          <baseinfo>
            <id>4</id>
            <body xsi:nil="true" />
          </baseinfo>
        </base>
    */
    select * from base for xml raw('baseinfo'),root('base'),elements xsinil;

    目前看起来,生成的xml结果似乎很不错,但是,如果我们想要将数据库中的body列改成xml的<data>元素,该如何修改呢?

    E.修改元素名

    /*
    结果:
        <base xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <baseinfo>
            <id>1</id>
            <data>aaaa</data>
          </baseinfo>
          <baseinfo>
            <id>2</id>
            <data>bbbb</data>
          </baseinfo>
          <baseinfo>
            <id>3</id>
            <data>dddd</data>
          </baseinfo>
          <baseinfo>
            <id>4</id>
            <data xsi:nil="true" />
          </baseinfo>
        </base>
    */
    select id,body data from base for xml raw('baseinfo'),root('base'),elements xsinil;

    现在的结果,基本上符合一个xml的基本格式,那么,我们设想,如果不给id,body指定列名,也不指定根元素名,也不指定元素名,那会出现什么记过呢?

    /*
    结果:
        1aaaa2bbbb3dddd4
    */
    --因为id为int类型,为使id不出现列名,我们使id+0
    --因为body为nvarchar类型,为使body不出现列名,我们使body+''
    select id+0,body+'' from base for xml raw(''), elements;

    但是,对上面的结果,我们似乎无法分清楚每条数据,而且id为4的空值也没有显示出来,如何进行修改呢?见下句.

    /*
    结果:
        1,aaaa;2,bbbb;3,dddd;4,null;
    */
    select id+0,',',isnull(body,'null')+'',';' from base for xml raw(''),elements;

    如此以来,似乎看到了没有列名给我们带的好处.其实上句还可以再修改些.

    /*
    结果:
        1,aaaa;2,bbbb;3,dddd;4,null;
    */
    select convert(nvarchar,id)+','+isnull(body,'null')+';' from base for xml raw(''),elements;

    我们再来修改,让让结果以另一种方式出现.

    /*
    结果:
        {1,aaaa}{2,bbbb}{3,dddd}{4,null}
    */
    select '{'+convert(nvarchar,id)+','+isnull(body,'null')+'}' from base for xml raw(''),elements;

    现在可以看到,我们可以根据自己的需要进行组合,生成我们需要的结果.

    在SQLServer2005中,已经支持了xml数据类型,因此,可以通过编写TYPE指令,将FOR XML查询的结果以xml数据类型进行返回,举例如下:

    declare @string nvarchar(1000)
    declare @xml xml
    
    /*
        消息257,级别16,状态3,第8行
        不允许从数据类型xml到nvarchar的隐式转换。请使用CONVERT函数来运行此查询。
    */
    --set @string=(select id,body from base for xml raw,type)
    
    set @xml=(select id,body from base for xml raw,type)

    最后,以一个常用的例子来介绍for xml raw模式的应用.

    建学生表student,表结构如下:

    列名 数据类型 允许空
    sid int 允许
    name nvarchar(50) 允许

    插入表数据如下:

    id name
    1 张三
    2 李四
    3 王五

    建课程表sclass,表结构如下:

    列名 数据类型 允许空
    cid int 允许
    name nvarchar(50) 允许

    插入表数据如下:

    id name
    1 语文
    2 数学
    3 英语

    建student_class表,表结构如下:

    列名 数据类型 允许空
    sid int  
    cid int  

    插入数据如下:

    cid sid
    1 1
    1 2
    1 3
    2 1
    3 2
    3 3

    至此,数据结果是:

    姓名 课程
    张三 语文
    张三 数学
    张三 英语
    李四 语文
    王五 数学
    王五 英语

    我们需要最后的结果形式如下:

    姓名 课程
    张三 语文,数学,英语
    李四 语文
    王五 数学,英语

    该如何实现呢?

    /*
    结果:
        张三    语文,数学,英语
        李四    语文
        王五    数学,英语
    */
    select [name],
                stuff(
                    (
                        select ','+[name]
                        from sclass
                        where cid in (
                                        select cid
                                        from student_class
                                        where student.sid=student_class.sid
                                    )
                        for xml raw(''),elements
                    ),
                1,1,'') sclass
    from student
  • 相关阅读:
    Java 读取某个目录下所有文件、文件夹
    poi根据excel模板导出Excel
    UML关系(泛化,实现,依赖,关联(聚合,组合))
    使用Git下载Hadoop的到本地Eclipse开发环境
    maven command to create your application
    Roo中的@Version
    oracle 给用户赋表空间
    hiberante 二级缓存设置
    procedure
    Oracle综合数据库管理命令集
  • 原文地址:https://www.cnblogs.com/oneword/p/1945061.html
Copyright © 2020-2023  润新知