1

我目前正在尝试使用 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

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

4

3 回答 3

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(),这是表的名称。
然后我们遍历元素并<Rows>为每个元素打开一个。
现在我们遍历当前元素中的所有属性并添加您的<DynamicColumn>. 我们可以使用local-name()来获取属性的名称并$a检索其值。

于 2019-12-06T21:05:13.340 回答
0

您可以使用 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>
于 2019-12-06T18:21:24.673 回答
0

@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>
于 2019-12-06T20:13:03.067 回答