我有一个类似于以下结构的xml文件:
<root>
<companies>
<company>
<name>XYZ Co. </name>
<addresses>
<address>
<street>12 Light Street</street>
</address>
<address>
<street>44 King Street</street>
<contacts>
<contact>
<fullName>Bob</fullName>
</contact>
<contact>
<fullName>Alice</fullName>
</contact>
</contacts>
</address>
</addresses>
</company>
</companies>
...
...
</root>
因此,可能会有许多公司 地址,并且在地址中可能会有很多联系人。现在我试图查询这个xml来插入相关的表(T-SQL)。 表格设计如下:
我看到过类似的问题:Bulk insert nested xml with foreign key as identity column of first table,但依赖其中一个父字段是唯一的。
我正在考虑沿着光标路走下去......希望有更好的选择。任何帮助将不胜感激。
非常感谢
答案 0 :(得分:2)
此解决方案依赖于将XML加载到XML类型的变量@xml
中。如果您需要帮助,请致电; - )
WITH MyCompanies AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS CompID
,Comp.value('name[1]','varchar(max)') AS Comp_Name
,Comp.query('.') AS Comp_InnerXML
FROM @xml.nodes('/root/companies/company') AS A(Comp)
)
,TheAddresses AS
(
SELECT MyCompanies.*
,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS AddrID
,Addr.value('street[1]','varchar(max)') AS Addr_Street
,Addr.query('.') AS Addr_InnerXML
FROM MyCompanies
OUTER APPLY Comp_InnerXML.nodes('company/addresses/address') AS A(Addr)
)
SELECT TheAddresses.*
,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS ContID
,Cont.value('fullName[1]','varchar(max)') AS Cont_FullName
INTO #temp
FROM TheAddresses
OUTER APPLY Addr_InnerXML.nodes('address/contacts/contact') AS C(Cont);
SELECT * FROM #temp;
结果
+--------+-----------+--------+-----------------+--------+---------------+
| CompID | Comp_Name | AddrID | Addr_Street | ContID | Cont_FullName |
+--------+-----------+--------+-----------------+--------+---------------+
| 1 | XYZ Co. | 1 | 12 Light Street | 1 | NULL |
+--------+-----------+--------+-----------------+--------+---------------+
| 1 | XYZ Co. | 2 | 44 King Street | 2 | Bob |
+--------+-----------+--------+-----------------+--------+---------------+
| 1 | XYZ Co. | 2 | 44 King Street | 3 | Alice |
+--------+-----------+--------+-----------------+--------+---------------+
| 2 | ABC Co. | 3 | 12 ABC Street | 4 | NULL |
+--------+-----------+--------+-----------------+--------+---------------+
| 2 | ABC Co. | 4 | 44 ABC Street | 5 | Bob ABC |
+--------+-----------+--------+-----------------+--------+---------------+
| 2 | ABC Co. | 4 | 44 ABC Street | 6 | Alice ABC |
+--------+-----------+--------+-----------------+--------+---------------+
在#temp中你有数据。使用DISTINCT
从那里进行插入...
--Your companies
SELECT DISTINCT CompID,Comp_Name FROM #temp;
--Your address
SELECT DISTINCT CompID,AddrID,Addr_Street FROM #temp;
--Your contacts
SELECT DISTINCT AddrID,ContID,Cont_FullName FROM #temp;
此查询将数据转换为表格数据。
但是:您应该将其插入相关的表格(公司,地址,联系人),而不是 all in one 。
您可以使用带有ROW_NUMBER
的{{1}}来创建虚拟ID,以生成虚拟ID,但这仅适用于第一次运行。
OVER(PARTITION BY ...)
结果
SELECT Comp.value('name[1]','varchar(max)') AS Comp_Name
,Addr.value('street[1]','varchar(max)') AS Addr_Street
,Cont.value('fullName[1]','varchar(max)') AS Cont_FullName
FROM @xml.nodes('/root/companies/company') AS A(Comp)
OUTER APPLY Comp.nodes('addresses/address') AS B(Addr)
OUTER APPLY Addr.nodes('contacts/contact') AS C(Cont)