FOR XML EXPLICIT 中的 ORDER BY 子句

ORDER BY Clause in FOR XML EXPLICIT

提问人:Paul Cauchon 提问时间:10/26/2017 最后编辑:Paul Cauchon 更新时间:10/27/2017 访问量:770

问:

我有一个相当大的查询(十几个表中有 25 个标签;~1500 行),需要使用 FOR XML EXPLICIT 将其格式化为 XML。不幸的是,此文件的使用者要求使用 CDATA 标记,否则我将使用 FOR XML PATH。

这就是我要找的:

<elem elem_att1="..." elem_att2="1" elem_att3="...">
    <a>...</a>            
    <b>...</b>
    <c>...</c>
    <d>...</d>
    <e>
        <e1 e1_att1="..." e1_att2="1">
            <e11>...</e11>
            <e12><![CDATA[...]]></e12>
            <e13><![CDATA[...]]></e13>
        </e1>
        <e1 e1_att1="..." e1_att2="2">
            <e11>...</e11>
            <e12><![CDATA[...]]></e12>
            <e13><![CDATA[...]]></e13>
        </e1>
        <e1 e1_att1="..." e1_att2="3">
            <e11>...</e11>
            <e12><![CDATA[...]]></e12>
            <e13><![CDATA[...]]></e13>
        </e1>
    </e>
    <f>
        <f1 f1_att1="..." f1_att2="..." />
        <f2 f2_att1="..." f2_att2="..." />
        <f3 f3_att1="..." f3_att2="..." />
    </f>
</elem>

假设在查询中正确定义了以下标记和父映射:

      Tag | Parent
elem  2   | 1
a     3   | 2
b     4   | 2
c     5   | 2
d     6   | 2
e     7   | 2
e1    8   | 7
e11   9   | 8
e12   10  | 8
e13   11  | 8
f     12  | 2
f1    13  | 12
f2    14  | 12
f3    15  | 12

我已经完成了大约 90% 的查询,但遇到了与通用表中标签顺序相关的问题。我希望看到从查询返回的表的前两列的以下输出:

Tag | Parent
2   | 1
3   | 2
4   | 2
5   | 2
6   | 2
7   | 2 <-- beginning of the "e" element
8   | 7 <-- first instance of the "e1" element
9   | 8
10  | 8
11  | 8
8   | 7 <-- second instance of the "e1" element
9   | 8
10  | 8
11  | 8
8   | 7 <-- third and final instance of the "e1" element
9   | 8
10  | 8
11  | 8
12  | 2 <-- beginning of the "f" element
13  | 12
14  | 12
15  | 12

相反,我将其作为查询输出的前两列:

Tag | Parent
2   | 1
3   | 2
4   | 2
5   | 2
6   | 2
7   | 2 <-- beginning of the "e" element
12  | 2 <-- beginning of the "f" element
13  | 12
14  | 12
15  | 12
8   | 7 <--first instance of the "e1" element
9   | 8
10  | 8
11  | 8
8   | 7 <-- second instance of the "e1" element
9   | 8
10  | 8
11  | 8
8   | 7 <-- third and final instance of the "e1" element
9   | 8
10  | 8
11  | 8

这显然会生成格式错误的 XML,如下所示:

<elem elem_att1="..." elem_att2="1" elem_att3="...">
    <a>...</a>            
    <b>...</b>
    <c>...</c>
    <d>...</d>
    <e />
    <f>
        <f1 f1_att1="..." f1_att2="..." />
        <f2 f2_att1="..." f2_att2="..." />
        <f3 f3_att1="..." f3_att2="..." />
    </f>
        <e1 e1_att1="..." e1_att2="1">
            <e11>...</e11>
            <e12><![CDATA[...]]></e12>
            <e13><![CDATA[...]]></e13>
        </e1>
        <e1 e1_att1="..." e1_att2="2">
            <e11>...</e11>
            <e12><![CDATA[...]]></e12>
            <e13><![CDATA[...]]></e13>
        </e1>
        <e1 e1_att1="..." e1_att2="3">
            <e11>...</e11>
            <e12><![CDATA[...]]></e12>
            <e13><![CDATA[...]]></e13>
        </e1>
    </e>
</elem>

查询阻塞并引发以下错误:

Msg 6833, Level 16, State 1, Line 2
Parent tag ID 7 is not among the open tags. FOR XML EXPLICIT requires parent tags to be opened first. Check the ordering of the result set.

这是我的条款:order by

order by [elem!2!att2], [e1!8!att2]

如果我将子句更改为order by

order by [elem!2!att2], tag, [e1!8!att2]

查询成功执行,但元素的所有子记录都嵌套在最后一个元素下:e1e1

<elem elem_att1="..." elem_att2="1" elem_att3="...">
    <a>...</a>            
    <b>...</b>
    <c>...</c>
    <d>...</d>
    <e>
        <e1 e1_att1="..." e1_att2="1" />
        <e1 e1_att1="..." e1_att2="2" />
        <e1 e1_att1="..." e1_att2="3">
            <e11>...</e11>
            <e11>...</e11>
            <e11>...</e11>
            <e12><![CDATA[...]]></e12>
            <e12><![CDATA[...]]></e12>
            <e12><![CDATA[...]]></e12>
            <e13><![CDATA[...]]></e13>
            <e13><![CDATA[...]]></e13>
            <e13><![CDATA[...]]></e13>
        </e1>
    </e>
    <f>
        <f1 f1_att1="..." f1_att2="..." />
        <f2 f2_att1="..." f2_att2="..." />
        <f3 f3_att1="..." f3_att2="..." />
    </f>
</elem>

实际问题:

是什么原因导致其子项在子项的种群之前填充在结果集中?fe

我希望这是一个相对常见的错误,其解决方案足够抽象,无需复制超过 1500 行代码即可中继。

sql-server for-xml-explicit

评论

1赞 Shnugo 10/27/2017
对不起,我没有经验......如果仍需要帮助,可以尝试使用最少的数据集设置独立方案来重现问题。作为一种解决方法,有两种可能性:1)告诉消费者,应该使用适当的工具读取 XML。 已经过时了,这不应该是你的问题。2)创建带有唯一占位符的XML,并在字符串级别引入with(我现在必须去洗手)。提示:不能将字符串-xml存储在本机XML中。它将被自动更换。EXPLICITCDATAPATHCDATAREPLACECDATA
0赞 Paul Cauchon 10/27/2017
感谢您@Shnugo提示。我认为可能值得再来一轮反击CDATA标签。
0赞 Shnugo 10/27/2017
您与消费者讨论的更多论据:stackoverflow.com/a/39034049/5089204(以及那里的链接)。在几种情况下,将隐式丢失(任何转换为字符串)。即使你设法把它们放到你的XML中,你也不能确定你会保留它们。CDATACDATA

答:

0赞 spodger 10/26/2017 #1

我已经很久没有使用它了,但你试过了吗

order by [elem!2!att2], [e], [e1!8!att2]

order by [elem!2!att2], 7, [e1!8!att2]

评论

0赞 Paul Cauchon 10/26/2017
其中第一个会导致错误,指出 [e] 不是有效列,第二个无法更正排序问题。
1赞 spodger 10/26/2017
我说好久不见了!不好意思!:-)