从具有值和名称的数据 table 中使用可变元素名称创建 XML
Create XML with variable element names from a data table with values and names
我找不到相关的 post,所以我决定问一下。
我的 SQL 服务器数据库中有以下 table:
ID attname value
---------------------------------
22405543 blktradind N
22405543 brkref IRVTGB2X
22405543 buyamt 104650.2000
22405543 buycurref USD
22405543 Buy53ref
22405543 Buy56ref
22405543 Buy57ref IRVTBEBB
如何使用 FOR XML 变体将此 table 转换为基于每条消息具有的 "attname" 的动态 XML 结果?
对于上面的摘录,期望的结果是:
<Message id=22405543>
<blktradind>N</blktradind>
<brkref>IRVTGB2X</brkref>
<buyamt>104650.2000</buyamt>
<buycurref>USD</buycurref>
<buy53ref />
<buy56ref />
<buy57ref>IRVTBEBB</buy57ref>
</Message>
谢谢
据我所知,除了在查询中操作数据类型和字段名称外,无法控制在 FOR XML 输出中生成输出的方式。
您需要像往常一样生成它,然后可能使用 XSLT 重新处理它以使其成为您想要的。
如果服务器支持 CLR,这实际上可以在服务器上完成。
这通常不可能。 SQL 服务器不支持输出的可变列别名。但也有解决方法:
字符串连接
该方法有点难看,因为我通常不喜欢通过字符串连接创建 XML。但是通过用 SELECT FOR XML PATH
本身包装值,这甚至对于像 <> or &
这样的禁止字符也是稳定的。
DECLARE @tbl TABLE(ID BIGINT,attname NVARCHAR(100),value NVARCHAR(100));
INSERT INTO @tbl VALUES
(22405543,'blktradind','N')
,(22405543,'brkref','IRVTGB2X')
,(22405543,'buyamt','104650.2000')
,(22405543,'buycurref','USD')
,(22405543,'Buy53ref',NULL)
,(22405543,'Buy56ref',NULL)
,(22405543,'Buy57ref','IRVTBEBB');
WITH DistinctIDs AS
(
SELECT DISTINCT ID FROM @tbl
)
SELECT ID AS [@id]
,(
SELECT CAST(N'<' + attname + N'>' + ISNULL((SELECT value AS [*] FOR XML PATH('')),N'') + N'</' + attname + N'>' AS XML)
FROM @tbl AS tbl
WHERE tbl.ID=DistinctIDs.ID
FOR XML PATH(''),TYPE
)
FROM DistinctIDs
FOR XML PATH('Message')
结果
<Message id="22405543">
<blktradind>N</blktradind>
<brkref>IRVTGB2X</brkref>
<buyamt>104650.2000</buyamt>
<buycurref>USD</buycurref>
<Buy53ref />
<Buy56ref />
<Buy57ref>IRVTBEBB</Buy57ref>
</Message>
动态SQL
您可以动态构建完整的语句并使用 EXEC(@cmd)
来执行它。像这样:
(注意!!:获取ID的SELECT TOP 1
不适合实际数据!)
DECLARE @cmd NVARCHAR(MAX)=
(
SELECT 'SELECT ''' + CAST((SELECT TOP 1 ID FROM @tbl) AS NVARCHAR(100)) + ''' AS [@id] '
+ (
SELECT ',''' + ISNULL(value,'') + ''' AS [' + attname + ']'
FROM @tbl
FOR XML PATH('')
)
+ ' FOR XML PATH(''Message'')'
);
EXEC(@cmd)
我找不到相关的 post,所以我决定问一下。
我的 SQL 服务器数据库中有以下 table:
ID attname value
---------------------------------
22405543 blktradind N
22405543 brkref IRVTGB2X
22405543 buyamt 104650.2000
22405543 buycurref USD
22405543 Buy53ref
22405543 Buy56ref
22405543 Buy57ref IRVTBEBB
如何使用 FOR XML 变体将此 table 转换为基于每条消息具有的 "attname" 的动态 XML 结果?
对于上面的摘录,期望的结果是:
<Message id=22405543>
<blktradind>N</blktradind>
<brkref>IRVTGB2X</brkref>
<buyamt>104650.2000</buyamt>
<buycurref>USD</buycurref>
<buy53ref />
<buy56ref />
<buy57ref>IRVTBEBB</buy57ref>
</Message>
谢谢
据我所知,除了在查询中操作数据类型和字段名称外,无法控制在 FOR XML 输出中生成输出的方式。
您需要像往常一样生成它,然后可能使用 XSLT 重新处理它以使其成为您想要的。
如果服务器支持 CLR,这实际上可以在服务器上完成。
这通常不可能。 SQL 服务器不支持输出的可变列别名。但也有解决方法:
字符串连接
该方法有点难看,因为我通常不喜欢通过字符串连接创建 XML。但是通过用 SELECT FOR XML PATH
本身包装值,这甚至对于像 <> or &
这样的禁止字符也是稳定的。
DECLARE @tbl TABLE(ID BIGINT,attname NVARCHAR(100),value NVARCHAR(100));
INSERT INTO @tbl VALUES
(22405543,'blktradind','N')
,(22405543,'brkref','IRVTGB2X')
,(22405543,'buyamt','104650.2000')
,(22405543,'buycurref','USD')
,(22405543,'Buy53ref',NULL)
,(22405543,'Buy56ref',NULL)
,(22405543,'Buy57ref','IRVTBEBB');
WITH DistinctIDs AS
(
SELECT DISTINCT ID FROM @tbl
)
SELECT ID AS [@id]
,(
SELECT CAST(N'<' + attname + N'>' + ISNULL((SELECT value AS [*] FOR XML PATH('')),N'') + N'</' + attname + N'>' AS XML)
FROM @tbl AS tbl
WHERE tbl.ID=DistinctIDs.ID
FOR XML PATH(''),TYPE
)
FROM DistinctIDs
FOR XML PATH('Message')
结果
<Message id="22405543">
<blktradind>N</blktradind>
<brkref>IRVTGB2X</brkref>
<buyamt>104650.2000</buyamt>
<buycurref>USD</buycurref>
<Buy53ref />
<Buy56ref />
<Buy57ref>IRVTBEBB</Buy57ref>
</Message>
动态SQL
您可以动态构建完整的语句并使用 EXEC(@cmd)
来执行它。像这样:
(注意!!:获取ID的SELECT TOP 1
不适合实际数据!)
DECLARE @cmd NVARCHAR(MAX)=
(
SELECT 'SELECT ''' + CAST((SELECT TOP 1 ID FROM @tbl) AS NVARCHAR(100)) + ''' AS [@id] '
+ (
SELECT ',''' + ISNULL(value,'') + ''' AS [' + attname + ']'
FROM @tbl
FOR XML PATH('')
)
+ ' FOR XML PATH(''Message'')'
);
EXEC(@cmd)