为 Table 数据和列定义生成 xml
Generate xml for Table data and column definitions
我目前正在尝试使用 SQL 语句生成 XML,其中 returns 来自 table 的数据,以及 table 名称、列名和相关数据。所以table加上数据的结构。整个事情应该保持动态,因此 table 名称的规范足以生成 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>
这里重要的是 table 名称和具有相应数据记录的列名称。
目前我正在尝试使用 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 路径:
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>
@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;
Output
<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>
我希望我没有弄错...从你的问题来看,你需要一种通用的方法来仅从 table 的名称创建这个动态结构。因此,您提供的示例并不是您实际需要的 table。正确吗?
如果这是真的,您可以看看 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
模式查询将 return this
SELECT * FROM dbo.AnyTable FOR XML AUTO
--结果以table的名称为元素名,所有列为属性
<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()
,这是 table 的名称。
然后我们运行遍历元素,并为每个元素打开一个<Rows>
。
现在我们 运行 通过当前元素内的所有属性并添加您的 <DynamicColumn>
。我们可以使用 local-name()
获取属性的名称并使用 $a
检索其值。
我目前正在尝试使用 SQL 语句生成 XML,其中 returns 来自 table 的数据,以及 table 名称、列名和相关数据。所以table加上数据的结构。整个事情应该保持动态,因此 table 名称的规范足以生成 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>
这里重要的是 table 名称和具有相应数据记录的列名称。
目前我正在尝试使用 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 路径:
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>
@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;
Output
<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>
我希望我没有弄错...从你的问题来看,你需要一种通用的方法来仅从 table 的名称创建这个动态结构。因此,您提供的示例并不是您实际需要的 table。正确吗?
如果这是真的,您可以看看 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
模式查询将 return this
SELECT * FROM dbo.AnyTable FOR XML AUTO
--结果以table的名称为元素名,所有列为属性
<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()
,这是 table 的名称。
然后我们运行遍历元素,并为每个元素打开一个<Rows>
。
现在我们 运行 通过当前元素内的所有属性并添加您的 <DynamicColumn>
。我们可以使用 local-name()
获取属性的名称并使用 $a
检索其值。