围绕根Xml节点中的所有行(消除列名称节点)

时间:2017-02-13 17:24:10

标签: sql sql-server xml tsql

我的表只有一列类型为Xml且名为 Xml 的列。 每行代表一个<recipient>项。

<receipt>
  <memberid>55555555</memberid>
  <purchaseid>4408888888859447</purchaseid>
  <time>2017-02-01</time>
  <depID>50277</depID>
  <amount>1398</amount>
  <theme>Herr</theme>
  <parentgroup></parentgroup>
</receipt>

我想要做的是在<recipients>的一个父节点中包围所有这些项目,这样它们看起来就像这样

<recipients>
    <receipt>
      <memberid>55555555</memberid>
      <purchaseid>4408888888859447</purchaseid>
      <time>2017-02-01</time>
      <depID>50277</depID>
      <amount>1398</amount>
      <theme>Herr</theme>
      <parentgroup></parentgroup>
    </receipt>
    <receipt>
      <memberid>55555555</memberid>
      <purchaseid>4408888888859447</purchaseid>
      <time>2017-02-01</time>
      <depID>50277</depID>
      <amount>1398</amount>
      <theme>Herr</theme>
      <parentgroup></parentgroup>
    </receipt>
    <receipt>
      <memberid>55555555</memberid>
      <purchaseid>4408888888859447</purchaseid>
      <time>2017-02-01</time>
      <depID>50277</depID>
      <amount>1398</amount>
      <theme>Herr</theme>
      <parentgroup></parentgroup>
    </receipt>
</recipients>

当我运行查询时:

SELECT [xml] 
  FROM MyTable
FOR XML PATH('recipients')

我为每条记录获得了额外的<xml>节点,这正是我想要摆脱的。

2 个答案:

答案 0 :(得分:2)

Declare @YourTable table (ID int,XML xml)
Insert Into @YourTable values
(1,'<receipt><memberid>55555555</memberid><purchaseid>4408888888859447</purchaseid><time>2017-02-01</time><depID>50277</depID> <amount>1398</amount><theme>Herr</theme><parentgroup></parentgroup></receipt>'),
(2,'<receipt><memberid>66666666</memberid><purchaseid>9999999999999999</purchaseid><time>2017-02-01</time><depID>50277</depID> <amount>1398</amount><theme>Herr</theme><parentgroup></parentgroup></receipt>')

Select XML AS [*]
 From  @YourTable
 For XML Path(''),Root('recipients')

返回

<recipients>
  <receipt>
    <memberid>55555555</memberid>
    <purchaseid>4408888888859447</purchaseid>
    <time>2017-02-01</time>
    <depID>50277</depID>
    <amount>1398</amount>
    <theme>Herr</theme>
    <parentgroup />
  </receipt>
  <receipt>
    <memberid>66666666</memberid>
    <purchaseid>9999999999999999</purchaseid>
    <time>2017-02-01</time>
    <depID>50277</depID>
    <amount>1398</amount>
    <theme>Herr</theme>
    <parentgroup />
  </receipt>
</recipients>
  

修改

由于Shnugo的背景信息而更新了答案。一如既往,非常感谢。

答案 1 :(得分:2)

这不是新的答案,只是一些背景。

此“技巧”有效,因为生成的列无名。

看看这个:

Declare @Dummy table (SomeValue INT)
Insert Into @Dummy values(1);

--Query                                --Column's Caption
----------------------------------------------------------
SELECT SomeValue FROM @Dummy;          --SomeValue
SELECT SomeValue+1-1 FROM @Dummy       --nameless due to the calculation
SELECT ISNULL(SomeValue,0) FROM @Dummy --nameless due to the function's usage

任何类型的函数计算或使用都将导致无名列。尝试将SELECT ... INTO ... FROMWITH CTE AS (SELECT ...)与未命名的列一起使用,您将获得例外。

FOR XML PATH同意,了解这一点非常重要。如果有列名,XML引擎将使用它作为元素的名称。

试试这个(约翰为样本代码)

Declare @YourTable table (ID int,XML xml)
Insert Into @YourTable values
(1,'<receipt><memberid>55555555</memberid><purchaseid>4408888888859447</purchaseid><time>2017-02-01</time><depID>50277</depID> <amount>1398</amount><theme>Herr</theme><parentgroup></parentgroup></receipt>'),
(2,'<receipt><memberid>66666666</memberid><purchaseid>9999999999999999</purchaseid><time>2017-02-01</time><depID>50277</depID> <amount>1398</amount><theme>Herr</theme><parentgroup></parentgroup></receipt>')

John的答案因使用函数

而起作用
Select cast(XML as xml) 
 From  @YourTable
 For XML Path(''),Root('recipients')

使用AS [*]作为别名也可以

Select XML AS [*]
 From  @YourTable
 For XML Path(''),Root('recipients')

最好的方式 - 正式使用 - 是这个

Select XML AS [node()] 
 From  @YourTable
 For XML Path(''),Root('recipients')

任何愚蠢的功能或计算都有这种效果

Select ISNULL(XML,XML)
 From  @YourTable
 For XML Path(''),Root('recipients')

每当人们使用FOR XML PATH作为连接工作时,他们就会在不知情的情况下使用它。典型的SELECT ', ' + SomeColumn会导致未命名的结果。如果没有', ',就会出现“奇怪”的元素......