从按列而非行组织的 SQL 创建类似 XML 的输出

问题描述 投票:0回答:1

我正在寻找一种有效的方法来生成看起来像 XML 的输出,按来自 SQL Server 2016 的原始数据列分组,针对特定的输出格式。

-- DDL and sample data population, start
DECLARE @tbl TABLE 
             ( 
                 ID INT IDENTITY PRIMARY KEY, 
                 FirstName VARCHAR(20), 
                 MiddleName VARCHAR(20), 
                 LastName VARCHAR(20)
             );

INSERT @tbl (FirstName, MiddleName, LastName) 
VALUES ('Fred', 'A.','Smith'),
       ('Anna', NULL,'Polack');

-- DDL and sample data population, end

我能做到:

DECLARE @Try XML

SET @Try = (SELECT 
                ('<Answer name = "FirstName">' + 
                 (SELECT FirstName AS 'value' 
                  FROM @tbl 
                  ORDER BY ID
                  FOR XML PATH(''), ROOT('repeat'), ELEMENTS XSINIL) +
                 '</Answer>') 
            +
            (SELECT
                 ('<Answer name = "MiddleName">' +
                  (SELECT MiddleName AS 'value'
                   FROM @tbl 
                   ORDER BY ID
                   FOR XML PATH(''), ROOT('repeat'), ELEMENTS XSINIL) + 
                  '</Answer>')
            +
            (SELECT
                 ('<Answer name = "LastName">' +
                  (SELECT LastName AS 'value'
                   FROM @tbl 
                   ORDER BY ID
                   FOR XML PATH(''), ROOT('repeat'), ELEMENTS XSINIL) + 
                  '</Answer>')
           )))

SELECT @Try

获得:

<Answer name="FirstName">
  <repeat xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <value>Fred</value>
    <value>Anna</value>
  </repeat>
</Answer>
<Answer name="MiddleName">
  <repeat xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <value>A.</value>
    <value xsi:nil="true" />
  </repeat>
</Answer>
<Answer name="LastName">
  <repeat xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <value>Smith</value>
    <value>Polack</value>
  </repeat>
</Answer>

我可以通过转换为文本并替换 xmlns 内容来获得所需的输出,即:

<Answer name="FirstName">
  <repeat>
    <value>Fred</value>
    <value>Anna</value>
  </repeat>
</Answer>
<Answer name="MiddleName">
  <repeat>
    <value>A.</value>
    <value xsi:nil="true" />
  </repeat>
</Answer>
<Answer name="LastName">
  <repeat>
    <value>Smith</value>
    <value>Polack</value>
  </repeat>
</Answer>

但是必须有一种更有效的方法来生成此输出而无需显式查询每一列(我的实际数据集有很多列)。

sql sql-server xml xquery
1个回答
0
投票

下面的代码会做你想做的,如果不是很有效的话。

  • 首先将整个表构建为 XML。
  • 然后它解析 XML 如下:
  • 获取第一行的节点并使用它们创建标题
    Answer/repeat
    节点。
  • 对于其中的每一个,重新查询所有值的 XML。
  • /row/*[local-name() = local-name($header)]
    这一步可能特别费钱
SELECT
  x.xml.query('
  for $header in /row[1]/*
  return
    <Answer name="{local-name($header)}">
      <repeat>{
        for $val in /row/*[local-name() = local-name($header)]
        return <value>{data($val)}</value>
      }</repeat>
    </Answer>')
FROM (
    SELECT *
    FROM @tbl
    FOR XML PATH('row'), TYPE
) x(xml);

db<>小提琴

使用现有代码并多次查询数据可能更有效。

© www.soinside.com 2019 - 2024. All rights reserved.