I am creating a table as follows:
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
I have a query which converts this into XML as :
SELECT A,B
FROM Test
ORDER BY A
FOR XML AUTO, ROOT ('myroot'), ELEMENTS
I need to use the above query as a subquery to get the following result:
A B
1 11
4 44
5 55
I am trying a query like this but it gives an error:
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 Cannot find either column "Z" or the user-defined function or aggregate "Z.Value", or the > name is ambiguous.
I can write a simple query like below to get the result but the requirement is that I have to convert it into XMl and then retrieve the same result from it using the subquery.
Select * from test order by A
I know that I can insert the records returned by For XML in a table variable and then use Cross apply to fetch the result but as said above, I am looking to get this done in a single query without any temporary table or temporary variable.
There're a several issues here. First, your xml looks like this:
<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>
And you're trying to fetch data as attributes (@A
, @B
). You need to fetch it as elements (A[1]
or (A/text())[1]
).
Second, you have to use type
keyword if you want your xml
to be xml type.
Third, to split data by rows you need nodes()
function. So your query becomes:
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)
BTW, I'd better to use attributes, like this:
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)