1

我正在创建一个表,如下所示:

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)

消息 4121,级别 16,状态 1,行 1 找不到列“Z”或用户定义的函数或聚合“Z.Value”,或者 > 名称不明确。

我可以编写一个如下所示的简单查询来获得结果,但要求是我必须将其转换为 XMl,然后使用子查询从中检索相同的结果。 Select * from test order by A

我知道我可以将 For XML 返回的记录插入表变量中,然后使用 Cross apply 来获取结果,但如上所述,我希望在没有任何临时表或临时变量的情况下在单个查询中完成此操作。

4

2 回答 2

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

于 2013-10-05T08:40:54.070 回答
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)

但我更喜欢在没有模式的情况下生成 XML (如果你写而不是 ,AUTO你的查询会崩溃),使用关键字以更具声明性的方式:dbo.TestTestPATH

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)
于 2013-10-05T08:03:27.650 回答