我正在创建一个表格如下:
CREATE TABLE dbo.Test
(
A int,
B int
)
GO
INSERT INTO Test VALUES (1, 11)
GO
INSERT INTO Test VALUES (5, 55)
GO
INSERT INTO Test VALUES (4, 44)
GO
我有一个查询将其转换为XML格式:
SELECT A,B
FROM Test
ORDER BY A
FOR XML AUTO, ROOT ('myroot'), ELEMENTS
我需要使用上面的查询作为子查询来获得以下结果:
A B
1 11
4 44
5 55
我正在尝试这样的查询,但它会出错:
SELECT Z.Value('@A', 'INT'),
Z.Value('@B', 'INT')
FROM (SELECT A, B
FROM Test
ORDER BY A
FOR XML AUTO,Elements, ROOT ('myroot')) Doc(Z)
Msg 4121,Level 16,State 1,Line 1 找不到列“Z”或用户定义的函数或聚合“Z.Value”,或者>名字含糊不清。
我可以编写一个简单的查询来获取结果,但要求是我必须将其转换为XMl,然后使用子查询从中检索相同的结果。
Select * from test order by A
我知道我可以在表变量中插入For XML返回的记录,然后使用Cross apply来获取结果,但如上所述,我希望在没有任何临时表或临时表的单个查询中完成此操作变量
答案 0 :(得分:1)
这里有几个问题。首先,你的xml看起来像这样:
<myroot>
<Test>
<A>1</A><B>11</B>
</Test>
<Test>
<A>4</A><B>44</B>
</Test>
<Test>
<A>5</A><B>55</B>
</Test>
</myroot>
您尝试将数据作为属性(@A
,@B
)获取。您需要将其作为元素(A[1]
或(A/text())[1]
)获取。
其次,如果您希望type
为xml类型,则必须使用xml
关键字。
第三,要按行拆分数据,需要nodes()
功能。所以你的查询变为:
select
D.Z.value('(A/text())[1]', 'int'),
D.Z.value('(B/text())[1]', 'int')
from (
select A, B
from Test
order by A
for xml auto, elements, root('myroot'), type
) as Doc(Z)
outer apply Doc.Z.nodes('myroot/Test') as D(Z)
顺便说一句,我最好使用属性,比如:
select
D.Z.value('@A', 'int'),
D.Z.value('@B', 'int')
from (
select A, B
from Test
order by A
for xml raw('Test'), root('myroot'), type
) as Doc(Z)
outer apply Doc.Z.nodes('myroot/Test') as D(Z)
<强> sql fiddle demo 强>
答案 1 :(得分:0)
您忘记了TYPE
模式(没有它你得到的是nvarchar而不是xml),而value
关键字应该是小写的。
试试这个:
SELECT Z.Z.value('@A', 'INT'),
Z.Z.value('@B', 'INT')
FROM (
SELECT A, B
FROM Test
ORDER BY A
FOR XML AUTO, ROOT ('myroot'), TYPE
) Doc(Doc)
CROSS APPLY Doc.nodes('/myroot/Test')Z(Z)
但我更倾向于在没有AUTO
模式的情况下生成XML(如果您编写dbo.Test
而不是Test
,则查询会中断),使用PATH
关键字以更加声明的方式:
SELECT Z.Z.value('@A', 'INT'),
Z.Z.value('@B', 'INT')
FROM (
SELECT A AS '@A', B AS '@B'
FROM dbo.Test
ORDER BY A
FOR XML PATH('Test'), ROOT ('myroot'), TYPE
) Doc(Doc)
CROSS APPLY Doc.nodes('/myroot/Test')Z(Z)