TSQL FOR XML格式

时间:2016-03-04 12:00:29

标签: sql-server xml tsql for-xml-path

我有一个表格,我想将其转换为XML格式。该表称为tempTable,并保存数据:

REF     DESC     QTY
100001  Normal   1
100002  OOH      1

我需要以这种给定的格式创建XML:

<row>
  <LIN NUM="1">
    <FLD NAME="REF">100001</FLD>
    <FLD NAME="DES">Normal</FLD>
    <FLD NAME="QTY">1</FLD>
  </LIN>
  <LIN NUM="2">
    <FLD NAME="REF">100002</FLD>
    <FLD NAME="DES">OOH</FLD>
    <FLD NAME="QTY">1</FLD>
  </LIN>
</row>

我尝试过以下代码:

SET @line = (SELECT '1' AS '@NUM', REF AS 'REF', DES AS 'DES', QTY AS 'QTY' FROM tempTable WHERE ORDER= @ORDER
FOR XML PATH('LIN'))

SELECT @line
FOR XML PATH

但是这会产生:

<row>
  <LIN NUM="1">
    <REF>100001</REF>
    <DES>Normal</DES>
    <QTY>1</QTY>
  </LIN>
  <LIN NUM="1">
    <REF>100002</REF>
    <DES>OOH</DES>
    <QTY>1</QTY>
  </LIN>
</row>

有谁知道我怎么做:

  • A)根据数量将'LIN''NUM'属性更改为增量 该订单的记录?
  • B)将“名称”属性添加到“LIN”详细信息并更改 字段名称为'FLD'。当我尝试将名称更改为“FLD”时 将值汇总到单个节点上,如下所示:

    <row>
      <LIN NUM="1">
        <FLD>100001Normal1</FLD>
      </LIN>
      <LIN NUM="1">
        <FLD>100002OOH1</FLD>
      </LIN>
    </row>
    

我假设我可以添加'NAME'属性来分隔值吗?

非常感谢任何建议/帮助。

由于

2 个答案:

答案 0 :(得分:5)

declare @tempTable table (Ref int, Des varchar(100), Qty int)
insert into @tempTable values (100001, 'Normal', 1), (100002, 'OOH', 1)

SELECT ROW_NUMBER() OVER (ORDER BY Ref) AS '@NUM',
     'REF' AS 'FLD/@NAME', REF AS 'FLD', '',
     'DES' AS 'FLD/@NAME', DES AS 'FLD', '',
     'QTY' AS 'FLD/@NAME', QTY AS 'FLD'

FROM @tempTable 
FOR XML PATH('LIN'), ROOT ('row')

产生

<row>
  <LIN NUM="1">
    <FLD NAME="REF">100001</FLD>
    <FLD NAME="DES">Normal</FLD>
    <FLD NAME="QTY">1</FLD>
  </LIN>
  <LIN NUM="2">
    <FLD NAME="REF">100002</FLD>
    <FLD NAME="DES">OOH</FLD>
    <FLD NAME="QTY">1</FLD>
  </LIN>
</row>

https://stackoverflow.com/a/25412657/4473405的帮助下,因为如果节点和select中的属性之间没有空字符串,SQL Server会给出错误:

  

以属性为中心的列'FLD / @ NAME'不得位于FOR XML PATH中XML层次结构中非属性中心的兄弟之后。

编辑:正如评论中所提到的,this post解释了为什么空引用技巧有效。

总结:

  • FOR XML PATH中,没有名称的列成为文本节点
    • NULL''因此成为空文本节点
    • 您可以使用AS *
    • 将命名列转换为未命名的列
    • 这有助于将先前输出的节点与下一个节点分开,以便SQL Server知道例如为下一列开始一个新元素。否则,当例如属性已经存在于它认为是“当前”元素
    • 时,它会变得混乱

答案 1 :(得分:0)

DECLARE @t TABLE (ref varchar(10), descr varchar(10), qty varchar(3))
insert into @t
values('100001', 'Normal', '1'),('10002','OOH','1')

SELECT ROW_NUMBER() OVER (ORDER BY a.ref) AS '@NUM',
(SELECT 'REF' AS 'FLD/@NAME'
 ,ref AS 'FLD'
FROM @t AS FLD
WHERE FLD.ref = a.ref
FOR XML PATH(''), TYPE),
(SELECT 'DESCR' AS 'FLD/@DESCR'
 ,descr AS 'FLD'
FROM @t AS FLD
WHERE FLD.ref = a.ref
FOR XML PATH(''), TYPE),
(SELECT 'QTY' AS 'FLD/@QTY'
 ,QTY AS 'FLD'
FROM @t AS FLD
WHERE FLD.ref = a.ref
FOR XML PATH(''), TYPE)
FROM @t AS a
FOR XML PATH('LIN'), ROOT('row')