将 XML 导入 SQL 并将多个节点合并为 1 列

Posted

技术标签:

【中文标题】将 XML 导入 SQL 并将多个节点合并为 1 列【英文标题】:Import XML into SQL and combine multiple nodes into 1 column 【发布时间】:2021-12-01 19:45:46 【问题描述】:

我有以下 XML

`<?xml version="1.0" encoding="UTF-8"?>
<AX_PDM_DATA>
<FilePath>\\N...</FilePath>
<ArticleCategory>

<CategoryName>test</CategoryName>
<Article>
<ItemId>123</ItemId>
<StoppedList>
<StoppedStatus>0</StoppedStatus>
<StopDescriptionItem/>
</StoppedList>
<ECOList>
<ECOStatus>0</ECOStatus>
<ECODescription/>
</ECOList>
<NCList>
<NC>1</NC>
<NCnumber>NC19012836</NCnumber>
<NCCategory>ODR</NCCategory>
<NCSubCategory>LP</NCSubCategory>
<NCDescription>test</NCDescription>
</NCList>
</Article>
<Article>
<ItemId>1234</ItemId>
<StoppedList>
<StoppedStatus>1</StoppedStatus>
<StopDescriptionItem/>
</StoppedList>
<ECOList>
<ECOStatus>0</ECOStatus>
<ECODescription/>
</ECOList>
<NCList>
<NC>0</NC>
<NCnumber/>
<NCCategory/>
<NCSubCategory/>
<NCDescription/>
</NCList>
</Article>
<Article>
<ItemId>456</ItemId>
<StoppedList>
<StoppedStatus>1</StoppedStatus>
<StopDescriptionItem/>
</StoppedList>
<ECOList>
<ECOStatus>0</ECOStatus>
<ECODescription/>
</ECOList>
<NCList>
<NC>0</NC>
<NCnumber/>
<NCCategory/>
<NCSubCategory/>
<NCDescription/>
</NCList>
</Article>
<Article>
<ItemId>74.489</ItemId>
<StoppedList>
<StoppedStatus>1</StoppedStatus>
<StopDescriptionItem/>
</StoppedList>
<ECOList>
<ECOStatus>0</ECOStatus>
<ECODescription/>
</ECOList>
<NCList>
<NC>0</NC>
<NCnumber/>
<NCCategory/>
<NCSubCategory/>
<NCDescription/>
</NCList>
</Article>
<Article>
<ItemId>AB050</ItemId>
<StoppedList>
<StoppedStatus>0</StoppedStatus>
<StopDescriptionItem />
</StoppedList>
<ECOList>
<ECOStatus>1</ECOStatus>
<ECODescription>SDsdfgadfhadfhadh arfgadfadfh</ECODescription>
</ECOList>
<NCList>
<NC>1</NC>
<NCnumber>NC18005166</NCnumber>
<NCCategory>ODR</NCCategory>
<NCSubCategory>LP</NCSubCategory>
<NCDescription>check </NCDescription>
</NCList>
<NCList>
<NC>1</NC>
<NCnumber>NC18005205</NCnumber>
<NCCategory>ODR</NCCategory>
<NCSubCategory>LP</NCSubCategory>
<NCDescription>check2</NCDescription>
</NCList>
</Article>
</ArticleCategory>
</AX_PDM_DATA>
`

我想将其导入 SQL 数据库。在某些情况下,在 Item 节点下我们可以有多个 NClist 节点。在 NClist 中,我有 NCnumbers,我想将它们放在一个列中。 现在我创建了以下 SQL 查询:

`DECLARE @XmlFile XML
SELECT @XmlFile = BulkColumn
FROM  OPENROWSET(BULK 'C:\temp\smallfile.xml', SINGLE_BLOB) x;

INSERT INTO GATEWAY_Table (ITEMID, STOPPEDSTATUS, STOPDESCRIPTIONITEM, ECOSTATUS, ECODESCRIPTION, NCNUMBER)
select
   MY_XML.Item.query('ItemId').value('.', 'VARCHAR(20)'),
   MY_XML.Item.query('StoppedList/StoppedStatus').value('.', 'VARCHAR(20)'),
   MY_XML.Item.query('StoppedList/StopDescriptionItem').value('.', 'VARCHAR(max)'),
   MY_XML.Item.query('ECOList/ECOStatus').value('.', 'VARCHAR(20)'),
   MY_XML.Item.query('ECOList/ECODescription').value('.', 'VARCHAR(max)'),
   XT2.NCLIST.query('NCList/NCnumber').value('.[1]', 'VARCHAR(max)')
FROM 
@XMlfile.nodes('AX_PDM_DATA/ArticleCategory/Article') AS MY_XML(Item)
cross apply
 item.nodes('NCList') as XT2(NCLIST)`

但我现在卡住了。谁可以帮忙?

提前致谢

【问题讨论】:

期望的输出是什么? XT2.NCLIST 已经选择了NCList 元素。你试过XT2.NCLIST.query('NCnumber').value('.[1]', 'VARCHAR(max)')吗? 我试过 XT2.NCLIST.query('NCnumber').value('.[1]', 'VARCHAR(max)') 然后我得到了 1 个值。我的目标是: 123 | 0 | |0||| ... AB050 | 0 | | 1| |sdsd| NC18000;19034;45456 等 提问时,您需要提供minimal reproducible example: (1) DDL 和样本数据填充,即 CREATE 表和 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上述#1 中的样本数据。 (4) 您的 SQL Server 版本 (SELECT @@version;)。 【参考方案1】:

请尝试以下解决方案。

不用.query()方法,.value()方法就够了。

SQL

DECLARE @GATEWAY_Table TABLE (
    ITEMID VARCHAR(20), 
    STOPPEDSTATUS VARCHAR(20), 
    STOPDESCRIPTIONITEM VARCHAR(max), 
    ECOSTATUS VARCHAR(20), 
    ECODESCRIPTION VARCHAR(max), 
    NCNUMBER VARCHAR(max)
);

DECLARE @XmlFile XML;

SELECT @XmlFile = BulkColumn
FROM  OPENROWSET(BULK 'e:\temp\smallfile.xml', SINGLE_BLOB) x;

INSERT INTO @GATEWAY_Table (ITEMID, STOPPEDSTATUS, STOPDESCRIPTIONITEM, ECOSTATUS, ECODESCRIPTION, NCNUMBER)
SELECT Item.value('(ItemId/text())[1]', 'VARCHAR(20)')
    , Item.value('(StoppedList/StoppedStatus/text())[1]', 'VARCHAR(20)')
    , Item.value('(StoppedList/StopDescriptionItem/text())[1]', 'VARCHAR(MAX)')
    , Item.value('(ECOList/ECOStatus/text())[1]', 'VARCHAR(20)')
    , Item.value('(ECOList/ECODescription/text())[1]', 'VARCHAR(MAX)')
    , NCLIST.value('(NCnumber/text())[1]', 'VARCHAR(MAX)')
FROM @XMlfile.nodes('/AX_PDM_DATA/ArticleCategory/Article') AS t1(Item)
CROSS APPLY t1.Item.nodes('NCList') as t2(NCLIST);

-- test
SELECT * FROM @GATEWAY_Table;

输出

+--------+---------------+---------------------+-----------+-------------------------------+------------+
| ITEMID | STOPPEDSTATUS | STOPDESCRIPTIONITEM | ECOSTATUS |        ECODESCRIPTION         |  NCNUMBER  |
+--------+---------------+---------------------+-----------+-------------------------------+------------+
| 123    |             0 | NULL                |         0 | NULL                          | NC19012836 |
| 1234   |             1 | NULL                |         0 | NULL                          | NULL       |
| 456    |             1 | NULL                |         0 | NULL                          | NULL       |
| 74.489 |             1 | NULL                |         0 | NULL                          | NULL       |
| AB050  |             0 | NULL                |         1 | SDsdfgadfhadfhadh arfgadfadfh | NC18005166 |
| AB050  |             0 | NULL                |         1 | SDsdfgadfhadfhadh arfgadfadfh | NC18005205 |
+--------+---------------+---------------------+-----------+-------------------------------+------------+

SQL #2

INSERT INTO @GATEWAY_Table (ITEMID, STOPPEDSTATUS, STOPDESCRIPTIONITEM, ECOSTATUS, ECODESCRIPTION, NCNUMBER)
SELECT Item.value('(ItemId/text())[1]', 'VARCHAR(20)')
    , Item.value('(StoppedList/StoppedStatus/text())[1]', 'VARCHAR(20)')
    , Item.value('(StoppedList/StopDescriptionItem/text())[1]', 'VARCHAR(MAX)')
    , Item.value('(ECOList/ECOStatus/text())[1]', 'VARCHAR(20)')
    , Item.value('(ECOList/ECODescription/text())[1]', 'VARCHAR(MAX)')
    , Item.query('data(NCList/NCnumber)').value('.', 'VARCHAR(MAX)')
FROM @XMlfile.nodes('/AX_PDM_DATA/ArticleCategory/Article') AS t1(Item);

输出

+--------+---------------+---------------------+-----------+-------------------------------+-----------------------+
| ITEMID | STOPPEDSTATUS | STOPDESCRIPTIONITEM | ECOSTATUS |        ECODESCRIPTION         |       NCNUMBER        |
+--------+---------------+---------------------+-----------+-------------------------------+-----------------------+
| 123    |             0 | NULL                |         0 | NULL                          | NC19012836            |
| 1234   |             1 | NULL                |         0 | NULL                          |                       |
| 456    |             1 | NULL                |         0 | NULL                          |                       |
| 74.489 |             1 | NULL                |         0 | NULL                          |                       |
| AB050  |             0 | NULL                |         1 | SDsdfgadfhadfhadh arfgadfadfh | NC18005166 NC18005205 |
+--------+---------------+---------------------+-----------+-------------------------------+-----------------------+

【讨论】:

感谢您的回答。对不起,我对输出的无能。您创建的输出几乎是正确的。只有我需要 AB050 作为一个具有多个 NCnumber 的项目,而不是每个 NCNumber 都是一个新行。 @GaituutH,我更新了答案。查看 SQL #2。 感谢这正是我想要的 @GaituutH,很高兴听到建议的解决方案对您有用。请不要忘记将其标记为答案。

以上是关于将 XML 导入 SQL 并将多个节点合并为 1 列的主要内容,如果未能解决你的问题,请参考以下文章

Linux怎么用命令合并多个文件为一个

Sql Server 中FOR XML PATH(‘‘)函数用法

Sql Server 中FOR XML PATH(‘‘)函数用法

将 XML 多个嵌套节点插入 SQL 表

将多个csv文件导入pandas并合并到一个DataFrame中

将 XML 数据插入到具有多个节点的 SQL 表中