【问题标题】:Generate xml for Table data and column definitions为表数据和列定义生成 xml
【发布时间】:2019-12-06 15:42:35
【问题描述】:

我目前正在尝试使用 SQL 语句生成 XML,该语句从表中返回数据,以及表名、列名和相关数据。所以表的结构加上数据。整个事情应该保持动态,这样一个表名的规范就足以生成xml。

因此,我希望是这样的:

<DynamicTable NAME="PARAMETER">
    <Rows>
        <DynamicColoumn NAME="PARAMETER_NAME" VALUE="PATH" />
        <DynamicColoumn NAME="PARAMETER_VALUE" VALUE="D:\Work\test.xml" />
        <DynamicColoumn NAME="PARAMETER_TYPE" VALUE="1" />
    </Rows>
    <Rows>
        <DynamicColoumn NAME="PARAMETER_NAME" VALUE=".." />
        <DynamicColoumn NAME="PARAMETER_VALUE" VALUE=".." />
        <DynamicColoumn NAME="PARAMETER_TYPE" VALUE="1" />
    </Rows>
</DynamicTable>

这里重要的是表名和列名与对应的数据记录。

目前我正在尝试使用 FOR XML EXPLICIT 来实现。但我未能将数据集分配给各个行。以及列名和数据集之间的分配。

我当前的 SQL:

SELECT  
    1               AS Tag,
    NULL            AS Parent,
    IS_T.TABLE_NAME AS [DynamicTable!1!NAME],
    NULL            AS [DynamicColoumn!2!NAME],
    NULL            AS [DynamicColoumn!2!VALUE]
FROM 
    INFORMATION_SCHEMA.TABLES AS IS_T
WHERE 
    IS_T.TABLE_NAME = 'PARAMETER'

UNION ALL

SELECT  
    2           AS Tag,
    1           AS Parent,
    'PARAMETER' AS [DynamicTable!1!NAME],
    P.PARA_NAME,
    P.PARA_VALUE    
FROM  
    PARAMETER AS P
FOR XML EXPLICIT

非常感谢您的帮助和方法!

【问题讨论】:

  • 请为您需要的单个表格提供一个完整样本。
  • 这已经通过我所代表的 XML 结构实现了。 XML 结构还指定了表的结构。带有“...”的值仅代表进一步的数据集,这些数据集也可能在表中。还是我误会了你?

标签: sql sql-server xml sql-server-2016 xml-generation


【解决方案1】:

我希望我没有弄错...从您的问题来看,您需要一种通用方法来仅根据表的名称创建此动态结构。因此,您提供的示例不是您需要的实际表格。对吗?

如果这是真的,您可能会查看FOR XML AUTO,它完全符合您的需求开箱即用:

首先我创建一个结构相当随机的表格,以模拟您的问题并用一些随机数据填充它:

CREATE TABLE dbo.AnyTable (
    SomeValue VARCHAR(50) NOT NULL,
    SomeOtherValue VARCHAR(50) NOT NULL,
    SomeNumber INT NOT NULL
);

INSERT dbo.AnyTable(SomeValue,SomeOtherValue,SomeNumber)
VALUES ('Value 1','Value 11',111)
      ,('Value 2','Value 22',222)
      ,('Value 3','Value 33',333);

--一个简单的AUTO-mode 查询会返回这个

SELECT * FROM dbo.AnyTable FOR XML AUTO

--结果以表名作为元素名,所有列作为属性

<dbo.AnyTable SomeValue="Value 1" SomeOtherValue="Value 11" SomeNumber="111" />
<dbo.AnyTable SomeValue="Value 2" SomeOtherValue="Value 22" SomeNumber="222" />
<dbo.AnyTable SomeValue="Value 3" SomeOtherValue="Value 33" SomeNumber="333" />

--您可以从这里开始使用 XQuery FLWOR 重新构建 XML:

SELECT
(
SELECT * FROM dbo.AnyTable FOR XML AUTO,TYPE
).query('<DynamicTable NAME="{local-name(/*[1])}">
         {
            for $r in /*
            return 
            <Rows>
            {
                for $a in $r/@*
                return <DynamicColumn NAME="{local-name($a)}" VALUE="{$a}" /> 
            }
            </Rows>
         }
         </DynamicTable>
        ');

--结果

<DynamicTable NAME="dbo.AnyTable">
  <Rows>
    <DynamicColumn NAME="SomeValue" VALUE="Value 1" />
    <DynamicColumn NAME="SomeOtherValue" VALUE="Value 11" />
    <DynamicColumn NAME="SomeNumber" VALUE="111" />
  </Rows>
  <Rows>
    <DynamicColumn NAME="SomeValue" VALUE="Value 2" />
    <DynamicColumn NAME="SomeOtherValue" VALUE="Value 22" />
    <DynamicColumn NAME="SomeNumber" VALUE="222" />
  </Rows>
  <Rows>
    <DynamicColumn NAME="SomeValue" VALUE="Value 3" />
    <DynamicColumn NAME="SomeOtherValue" VALUE="Value 33" />
    <DynamicColumn NAME="SomeNumber" VALUE="333" />
  </Rows>
</DynamicTable>

--清理

GO
DROP TABLE dbo.AnyTable;

简而言之,FLWOR 理念:

首先我们创建最外层的元素并使用第一个元素的local-name(),这是表的名称。
然后我们遍历元素并为每个元素打开一个&lt;Rows&gt;。
现在我们遍历当前元素中的所有属性并添加您的&lt;DynamicColumn&gt;。我们可以使用local-name() 获取属性的名称,使用$a 检索其值。

【讨论】:

  • 很好的答案,我这边+1!
【解决方案2】:

您可以用于xml路径:

CREATE TABLE dbo.PARAMETER (
    PARAMETER_NAME nvarchar(64) NOT NULL,
    PARAMETER_VALUE nvarchar(64) NOT NULL,
    PARAMETER_TYPE tinyint NOT NULL,
    CONSTRAINT PK_PARAMETER PRIMARY KEY (PARAMETER_NAME)
)

INSERT dbo.PARAMETER (PARAMETER_NAME,PARAMETER_VALUE,PARAMETER_TYPE)
VALUES ('PATH','D:\Work\test.xml',1),
    ('..','..',1),
    ('Test','TestValue',2);

SELECT 'PARAMETER' AS '@NAME',
    (SELECT
        (SELECT 'PARAMETER_NAME' AS '@NAME',
                p1.PARAMETER_NAME AS '@VALUE'
        FROM dbo.PARAMETER p1
        WHERE p1.PARAMETER_NAME=p.PARAMETER_NAME
        FOR XML PATH ('DynamicColoumn'),TYPE),
        (SELECT 'PARAMETER_VALUE' AS '@NAME',
                p2.PARAMETER_VALUE AS '@VALUE'
        FROM dbo.PARAMETER p2
        WHERE p2.PARAMETER_NAME=p.PARAMETER_NAME
        FOR XML PATH ('DynamicColoumn'),TYPE),
        (SELECT 'PARAMETER_TYPE' AS '@NAME',
                p3.PARAMETER_TYPE AS '@VALUE'
        FROM dbo.PARAMETER p3
        WHERE p3.PARAMETER_NAME=p.PARAMETER_NAME
        FOR XML PATH ('DynamicColoumn'),TYPE)
    FROM dbo.PARAMETER p
    FOR XML PATH('Rows'),TYPE)
FOR XML PATH ('DynamicTable');

输出:

<DynamicTable NAME="PARAMETER">
  <Rows>
    <DynamicColoumn NAME="PARAMETER_NAME" VALUE=".." />
    <DynamicColoumn NAME="PARAMETER_VALUE" VALUE=".." />
    <DynamicColoumn NAME="PARAMETER_TYPE" VALUE="1" />
  </Rows>
  <Rows>
    <DynamicColoumn NAME="PARAMETER_NAME" VALUE="PATH" />
    <DynamicColoumn NAME="PARAMETER_VALUE" VALUE="D:\Work\test.xml" />
    <DynamicColoumn NAME="PARAMETER_TYPE" VALUE="1" />
  </Rows>
  <Rows>
    <DynamicColoumn NAME="PARAMETER_NAME" VALUE="Test" />
    <DynamicColoumn NAME="PARAMETER_VALUE" VALUE="TestValue" />
    <DynamicColoumn NAME="PARAMETER_TYPE" VALUE="2" />
  </Rows>
</DynamicTable>

【讨论】:

    【解决方案3】:

    @PeterHe 公然重用虚构的 DDL 和样本数据填充,这是基于 XQuery FLWOR 表达式的解决方案。

    SQL

    -- DDL and sample data population, start
    USE tempdb;
    GO
    
    DROP TABLE IF EXISTS dbo.PARAMETER;
    
    CREATE TABLE dbo.PARAMETER (
        PARAMETER_NAME NVARCHAR(64) PRIMARY KEY,
        PARAMETER_VALUE NVARCHAR(64) NOT NULL,
        PARAMETER_TYPE TINYINT NOT NULL,
    );
    
    INSERT dbo.PARAMETER (PARAMETER_NAME,PARAMETER_VALUE,PARAMETER_TYPE)
    VALUES ('PATH','D:\Work\test.xml',1),
        ('..','..',1),
        ('Test','TestValue',2);
    -- DDL and sample data population, end
    
    SELECT (SELECT * FROM dbo.PARAMETER
    FOR XML PATH('row'), TYPE, ROOT('root')).query('<DynamicTable NAME="PARAMETER">
    {
        for $x in /root/row
        return <Rows>
                <DynamicColumn NAME="PARAMETER_NAME" VALUE="{$x/PARAMETER_NAME/text()}" />
                <DynamicColumn NAME="PARAMETER_VALUE" VALUE="{$x/PARAMETER_VALUE/text()}" />
                <DynamicColumn NAME="PARAMETER_TYPE" VALUE="{$x/PARAMETER_TYPE/text()}" />
            </Rows>
    }
    </DynamicTable>') AS Result;
    

    输出

    <DynamicTable NAME="PARAMETER">
      <Rows>
        <DynamicColumn NAME="PARAMETER_NAME" VALUE=".." />
        <DynamicColumn NAME="PARAMETER_VALUE" VALUE=".." />
        <DynamicColumn NAME="PARAMETER_TYPE" VALUE="1" />
      </Rows>
      <Rows>
        <DynamicColumn NAME="PARAMETER_NAME" VALUE="PATH" />
        <DynamicColumn NAME="PARAMETER_VALUE" VALUE="D:\Work\test.xml" />
        <DynamicColumn NAME="PARAMETER_TYPE" VALUE="1" />
      </Rows>
      <Rows>
        <DynamicColumn NAME="PARAMETER_NAME" VALUE="Test" />
        <DynamicColumn NAME="PARAMETER_VALUE" VALUE="TestValue" />
        <DynamicColumn NAME="PARAMETER_TYPE" VALUE="2" />
      </Rows>
    </DynamicTable>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-12
      • 2015-02-25
      • 2021-05-31
      • 1970-01-01
      • 2013-01-06
      • 1970-01-01
      • 2010-09-06
      相关资源
      最近更新 更多