XML 个节点 SQL
XML nodes with SQL
我有以下 XML 数据,并希望在 KS 中获取如下行的数据:
<DW>
<KS>
<KeyInfo Name="IlluSetting">
<KeyTypeValue>Text</KeyTypeValue>
<ValueString>yDipol90</ValueString>
</KeyInfo>
<KeyInfo Name="IlluSetting2">
<KeyTypeValue>Text</KeyTypeValue>
<ValueString>yDipol</ValueString>
</KeyInfo>
</KS>
<MDESC>Tx [mrad]</MDESC>
<MNUMBER>0.12102</MNUMBER>
</DW>
<DW>
<KS>
<KeyInfo Name="IlluSetting3">
<KeyTypeValue>Text</KeyTypeValue>
<ValueString>yDipol80</ValueString>
</KeyInfo>
</KS>
<MDESC>Ty [mrad]</MDESC>
<MNUMBER>0.12102</MNUMBER>
</DW>
有什么方法可以得到 Table 输出如下:
Name ValueString Name ValueString
-----------------------------------------------------------
IlluSetting yDipol90 IlluSetting2 yDipol
IlluSetting3 yDipol80
表示<KS>... </KS>
里面的数据会排成一行
非常感谢
请尝试以下解决方案。我们在这里做的事情叫做切碎,即将 XML 转换成 rectangular/relational 格式。
因为没有提供 DDL 和样本数据总体,所以我不敢妄下定论。
由于缺少根元素,提供的 XML 格式不正确,但 SQL 服务器允许处理 XML 个片段。
我们正在使用 XQuery 及其 .nodes()
和 .value()
方法。
SQL,方法 #1
-- DDL and sample data population, start
DECLARE @xml XML =
N'<DW>
<KS>
<KeyInfo Name="IlluSetting">
<KeyTypeValue>Text</KeyTypeValue>
<ValueString>yDipol90</ValueString>
</KeyInfo>
<KeyInfo Name="IlluSetting2">
<KeyTypeValue>Text</KeyTypeValue>
<ValueString>yDipol</ValueString>
</KeyInfo>
</KS>
<MDESC>Tx [mrad]</MDESC>
<MNUMBER>0.12102</MNUMBER>
</DW>
<DW>
<KS>
<KeyInfo Name="IlluSetting3">
<KeyTypeValue>Text</KeyTypeValue>
<ValueString>yDipol80</ValueString>
</KeyInfo>
</KS>
<MDESC>Ty [mrad]</MDESC>
<MNUMBER>0.12102</MNUMBER>
</DW>';
-- DDL and sample data population, end
SELECT c.value('KeyInfo[1]/@Name', 'VARCHAR(30)') AS name1
, c.value('(KeyInfo[1]/ValueString/text())[1]', 'VARCHAR(30)') AS ValueString1
, COALESCE(c.value('KeyInfo[2]/@Name', 'VARCHAR(30)'), '') AS name2
, COALESCE(c.value('(KeyInfo[2]/ValueString/text())[1]', 'VARCHAR(30)'), '') AS ValueString2
FROM @xml.nodes('/DW/KS') AS t(c);
输出
+--------------+--------------+--------------+--------------+
| name1 | ValueString1 | name2 | ValueString2 |
+--------------+--------------+--------------+--------------+
| IlluSetting | yDipol90 | IlluSetting2 | yDipol |
| IlluSetting3 | yDipol80 | | |
+--------------+--------------+--------------+--------------+
SQL,方法 #2
DECLARE @CrLf CHAR(2) = CHAR(13) + CHAR(10)
, @tokenCounter INT
, @i INT = 1;
-- Calculate max number of tokens in the <KS>
SET @tokenCounter = (SELECT MAX(c.value('count(KeyInfo)', 'INT'))
FROM @xml.nodes('/DW/KS') AS t(c));
DECLARE @SQL NVARCHAR(MAX) = 'SELECT ';
WHILE @i <= @tokenCounter BEGIN
SET @SQL += IIF(@i>1,', ','') + 'COALESCE(c.value(''KeyInfo[' + CAST(@i AS VARCHAR(3)) + ']/@Name'', ''VARCHAR(30)''), '''') AS NAME' + CAST(@i AS VARCHAR(3)) + @CrLf
SET @SQL += ', COALESCE(c.value(''(KeyInfo[' + CAST(@i AS VARCHAR(3)) + ']/ValueString/text())[1]'', ''VARCHAR(30)''), '''') AS ValueString' + CAST(@i AS VARCHAR(3)) + @CrLf
SET @i += 1
END
SET @SQL += 'FROM @xml.nodes(''/DW/KS'') AS t(c);';
-- just to see it
PRINT @sql;
-- we are ready at this point
EXEC sp_executesql @stmt = @SQL, @params = N'@xml xml', @xml = @xml;
我有以下 XML 数据,并希望在 KS 中获取如下行的数据:
<DW>
<KS>
<KeyInfo Name="IlluSetting">
<KeyTypeValue>Text</KeyTypeValue>
<ValueString>yDipol90</ValueString>
</KeyInfo>
<KeyInfo Name="IlluSetting2">
<KeyTypeValue>Text</KeyTypeValue>
<ValueString>yDipol</ValueString>
</KeyInfo>
</KS>
<MDESC>Tx [mrad]</MDESC>
<MNUMBER>0.12102</MNUMBER>
</DW>
<DW>
<KS>
<KeyInfo Name="IlluSetting3">
<KeyTypeValue>Text</KeyTypeValue>
<ValueString>yDipol80</ValueString>
</KeyInfo>
</KS>
<MDESC>Ty [mrad]</MDESC>
<MNUMBER>0.12102</MNUMBER>
</DW>
有什么方法可以得到 Table 输出如下:
Name ValueString Name ValueString
-----------------------------------------------------------
IlluSetting yDipol90 IlluSetting2 yDipol
IlluSetting3 yDipol80
表示<KS>... </KS>
里面的数据会排成一行
非常感谢
请尝试以下解决方案。我们在这里做的事情叫做切碎,即将 XML 转换成 rectangular/relational 格式。
因为没有提供 DDL 和样本数据总体,所以我不敢妄下定论。
由于缺少根元素,提供的 XML 格式不正确,但 SQL 服务器允许处理 XML 个片段。
我们正在使用 XQuery 及其 .nodes()
和 .value()
方法。
SQL,方法 #1
-- DDL and sample data population, start
DECLARE @xml XML =
N'<DW>
<KS>
<KeyInfo Name="IlluSetting">
<KeyTypeValue>Text</KeyTypeValue>
<ValueString>yDipol90</ValueString>
</KeyInfo>
<KeyInfo Name="IlluSetting2">
<KeyTypeValue>Text</KeyTypeValue>
<ValueString>yDipol</ValueString>
</KeyInfo>
</KS>
<MDESC>Tx [mrad]</MDESC>
<MNUMBER>0.12102</MNUMBER>
</DW>
<DW>
<KS>
<KeyInfo Name="IlluSetting3">
<KeyTypeValue>Text</KeyTypeValue>
<ValueString>yDipol80</ValueString>
</KeyInfo>
</KS>
<MDESC>Ty [mrad]</MDESC>
<MNUMBER>0.12102</MNUMBER>
</DW>';
-- DDL and sample data population, end
SELECT c.value('KeyInfo[1]/@Name', 'VARCHAR(30)') AS name1
, c.value('(KeyInfo[1]/ValueString/text())[1]', 'VARCHAR(30)') AS ValueString1
, COALESCE(c.value('KeyInfo[2]/@Name', 'VARCHAR(30)'), '') AS name2
, COALESCE(c.value('(KeyInfo[2]/ValueString/text())[1]', 'VARCHAR(30)'), '') AS ValueString2
FROM @xml.nodes('/DW/KS') AS t(c);
输出
+--------------+--------------+--------------+--------------+
| name1 | ValueString1 | name2 | ValueString2 |
+--------------+--------------+--------------+--------------+
| IlluSetting | yDipol90 | IlluSetting2 | yDipol |
| IlluSetting3 | yDipol80 | | |
+--------------+--------------+--------------+--------------+
SQL,方法 #2
DECLARE @CrLf CHAR(2) = CHAR(13) + CHAR(10)
, @tokenCounter INT
, @i INT = 1;
-- Calculate max number of tokens in the <KS>
SET @tokenCounter = (SELECT MAX(c.value('count(KeyInfo)', 'INT'))
FROM @xml.nodes('/DW/KS') AS t(c));
DECLARE @SQL NVARCHAR(MAX) = 'SELECT ';
WHILE @i <= @tokenCounter BEGIN
SET @SQL += IIF(@i>1,', ','') + 'COALESCE(c.value(''KeyInfo[' + CAST(@i AS VARCHAR(3)) + ']/@Name'', ''VARCHAR(30)''), '''') AS NAME' + CAST(@i AS VARCHAR(3)) + @CrLf
SET @SQL += ', COALESCE(c.value(''(KeyInfo[' + CAST(@i AS VARCHAR(3)) + ']/ValueString/text())[1]'', ''VARCHAR(30)''), '''') AS ValueString' + CAST(@i AS VARCHAR(3)) + @CrLf
SET @i += 1
END
SET @SQL += 'FROM @xml.nodes(''/DW/KS'') AS t(c);';
-- just to see it
PRINT @sql;
-- we are ready at this point
EXEC sp_executesql @stmt = @SQL, @params = N'@xml xml', @xml = @xml;