将 XML 列数据分解为 SQL 中的行
Shredding XML column data into rows in SQL
我有一个 xml 值
<ITEMS>
<ITEM><ID>1</ID><NAME>John</NAME></ITEM>
<ITEM><ID>5</ID><NAME>James</NAME></ITEM>
</ITEMS>
我可以使用以下查询将上面的 xml 分解成 ID 和 Name 列的表
Declare @X xml
select x.r.value('(ID)[1]','int') as [ID],
x.r.value('(DATA)[1]','VARCHAR(100)') AS [DATA]
FROM @X.nodes ('/ITEMS/ITEM') AS x(r)
但是当上面的 xml 连续出现时,我将如何做到这一点。
S.No COMPANY DATA
1 ABC </ITEMS><ITEM><ID>1</ID><NAME>John</Name>....
我需要像下面这样填充
S.No COMPANY ID NAME
1 ABC 1 John
2 ABC 5 James
Note : The Data column in the table is of varchar data type and not xml data type.
首先,您可以使用 CTE 将其转换为 XML 数据类型。第二种方式是通过派生的 table.
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (SequentialNo INT PRIMARY KEY, Company VARCHAR(20), [DATA] VARCHAR(MAX));
INSERT INTO @tbl (SequentialNo, Company, [DATA])
VALUES
(1, 'ABC', '<ITEMS>
<ITEM>
<ID>1</ID>
<NAME>John</NAME>
</ITEM>
<ITEM>
<ID>5</ID>
<NAME>James</NAME>
</ITEM>
</ITEMS>');
-- DDL and sample data population, end
-- Method #1
-- CTE
;WITH rs AS
(
SELECT *, TRY_CAST([DATA] AS XML) AS [xmldata]
FROM @tbl
)
SELECT SequentialNo
, Company
, col.value('(ID/text())[1]','INT') AS ID
, col.value('(NAME/text())[1]','VARCHAR(40)') AS [Name]
FROM rs AS tbl
CROSS APPLY tbl.[xmldata].nodes('/ITEMS/ITEM') AS tab(col);
-- Method #2
-- Derived table
SELECT SequentialNo
, Company
, col.value('(ID/text())[1]','INT') AS ID
, col.value('(NAME/text())[1]','VARCHAR(40)') AS [Name]
FROM (SELECT *, TRY_CAST([DATA] AS XML) AS [xmldata]
FROM @tbl) AS tbl
CROSS APPLY tbl.[xmldata].nodes('/ITEMS/ITEM') AS tab(col);
Output
+--------------+---------+----+-------+
| SequentialNo | Company | ID | Name |
+--------------+---------+----+-------+
| 1 | ABC | 1 | John |
| 1 | ABC | 5 | James |
+--------------+---------+----+-------+
我有一个 xml 值
<ITEMS>
<ITEM><ID>1</ID><NAME>John</NAME></ITEM>
<ITEM><ID>5</ID><NAME>James</NAME></ITEM>
</ITEMS>
我可以使用以下查询将上面的 xml 分解成 ID 和 Name 列的表
Declare @X xml
select x.r.value('(ID)[1]','int') as [ID],
x.r.value('(DATA)[1]','VARCHAR(100)') AS [DATA]
FROM @X.nodes ('/ITEMS/ITEM') AS x(r)
但是当上面的 xml 连续出现时,我将如何做到这一点。
S.No COMPANY DATA
1 ABC </ITEMS><ITEM><ID>1</ID><NAME>John</Name>....
我需要像下面这样填充
S.No COMPANY ID NAME
1 ABC 1 John
2 ABC 5 James
Note : The Data column in the table is of varchar data type and not xml data type.
首先,您可以使用 CTE 将其转换为 XML 数据类型。第二种方式是通过派生的 table.
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (SequentialNo INT PRIMARY KEY, Company VARCHAR(20), [DATA] VARCHAR(MAX));
INSERT INTO @tbl (SequentialNo, Company, [DATA])
VALUES
(1, 'ABC', '<ITEMS>
<ITEM>
<ID>1</ID>
<NAME>John</NAME>
</ITEM>
<ITEM>
<ID>5</ID>
<NAME>James</NAME>
</ITEM>
</ITEMS>');
-- DDL and sample data population, end
-- Method #1
-- CTE
;WITH rs AS
(
SELECT *, TRY_CAST([DATA] AS XML) AS [xmldata]
FROM @tbl
)
SELECT SequentialNo
, Company
, col.value('(ID/text())[1]','INT') AS ID
, col.value('(NAME/text())[1]','VARCHAR(40)') AS [Name]
FROM rs AS tbl
CROSS APPLY tbl.[xmldata].nodes('/ITEMS/ITEM') AS tab(col);
-- Method #2
-- Derived table
SELECT SequentialNo
, Company
, col.value('(ID/text())[1]','INT') AS ID
, col.value('(NAME/text())[1]','VARCHAR(40)') AS [Name]
FROM (SELECT *, TRY_CAST([DATA] AS XML) AS [xmldata]
FROM @tbl) AS tbl
CROSS APPLY tbl.[xmldata].nodes('/ITEMS/ITEM') AS tab(col);
Output
+--------------+---------+----+-------+
| SequentialNo | Company | ID | Name |
+--------------+---------+----+-------+
| 1 | ABC | 1 | John |
| 1 | ABC | 5 | James |
+--------------+---------+----+-------+