[英]Parse XML file in SQL with duplicated Tags
我正在尝试展平我的 XML 文件,但是当标签中有重复标签时会出现并发症。 我不确定如何向上移动标签链。 下面的例子。
DECLARE @xml AS XMl, @hDoc AS INT
SET @xml = '<Message>
<Body>
<SfkpgAcctAndHldgs>
<SfkpgAcct>UHS5465</SfkpgAcct>
<AcctSubLvl>
<Dsclsr>
<SfkpgAcct>450812361</SfkpgAcct>
<AcctHldr>
<LglPrsn>
<NmAndAdr>
<Nm>Foo</Nm>
<Adr>
<AdrLine>1 CORPORATE WAY, New York 15951</AdrLine>
<Ctry>US</Ctry>
</Adr>
</NmAndAdr>
<LEI>5493231HPIWHJS5QL7N39</LEI>
<Ownrsh>OWNR</Ownrsh>
</LglPrsn>
</AcctHldr>
<ShrhldgBal>
<ShrhldgTp>BENE</ShrhldgTp>
<Unit>1000</Unit>
</ShrhldgBal>
</Dsclsr>
<Dsclsr>
<SfkpgAcct>450812362</SfkpgAcct>
<AcctHldr>
<LglPrsn>
<NmAndAdr>
<Nm>Bar</Nm>
<Adr>
<AdrLine>2 CORPORATE WAY</AdrLine>
<AdrLine>New York</AdrLine>
<AdrLine>15951</AdrLine>
<Ctry>US</Ctry>
</Adr>
</NmAndAdr>
<LEI>5493231HP2342345QL7N39</LEI>
<Ownrsh>OWNR</Ownrsh>
</LglPrsn>
</AcctHldr>
<ShrhldgBal>
<ShrhldgTp>BENE</ShrhldgTp>
<Unit>300</Unit>
</ShrhldgBal>
</Dsclsr>
</AcctSubLvl>
</SfkpgAcctAndHldgs>
</Body>
</message>'
EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML
此查询获取每个 SfkpgAcctAndHldgs 并引入第一个 Dsclsr,有两个但只有第一个返回。
SELECT *
FROM OPENXML(@hDoc,'message/Body/SfkpgAcctAndHldgs') WITH (
SfkpgAcct NVARCHAR(MAX) 'SfkpgAcct'
, Dsclsr_SfkpgAcct NVARCHAR(MAX) 'AcctSubLvl/Dsclsr/SfkpgAcct'
, Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Nm NVARCHAR(MAX) 'AcctSubLvl/Dsclsr/AcctHldr/LglPrsn/NmAndAdr/Nm'
, Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Adr_AdrLine NVARCHAR(MAX) 'AcctSubLvl/Dsclsr/AcctHldr/LglPrsn/NmAndAdr/Adr/AdrLine'
, Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Adr_Ctry NVARCHAR(MAX) 'AcctSubLvl/Dsclsr/AcctHldr/LglPrsn/NmAndAdr/Adr/Ctry'
, Dsclsr_AcctHldr_LglPrsn_LEI NVARCHAR(MAX) 'AcctSubLvl/Dsclsr/AcctHldr/LglPrsn/LEI'
, Dsclsr_AcctHldr_LglPrsn_Ownrsh NVARCHAR(MAX) 'AcctSubLvl/Dsclsr/AcctHldr/LglPrsn/Ownrsh'
, Dsclsr_ShrhldgBal_ShrhldgTp NVARCHAR(MAX) 'AcctSubLvl/Dsclsr/ShrhldgBal/ShrhldgTp'
, Dsclsr_ShrhldgBal_Unit NVARCHAR(MAX) 'AcctSubLvl/Dsclsr/ShrhldgBal/Unit'
)
--SfkpgAcct AcctSubLvl_Dsclsr_SfkpgAcct Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Nm Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Adr_AdrLine Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Adr_Ctry Dsclsr_AcctHldr_LglPrsn_LEI Dsclsr_AcctHldr_LglPrsn_Ownrsh Dsclsr_AcctHldr_ShrhldgBal_ShrhldgTp Dsclsr_AcctHldr_ShrhldgBal_Unit
--UHS5465 450812361 Foo 1 CORPORATE WAY, New York 15951 US 5493231 HPIWHJS5QL7N39 OWNR BENE 1000
此查询查看 Dsclsr 级别,因此带回了这两行。 但是我不能 go 备份链以获得第一个 SfkpgAcct 值,这是我可以加入表格的唯一值。
SELECT *
FROM OPENXML(@hDoc,'message/Body/SfkpgAcctAndHldgs/AcctSubLvl/Dsclsr') WITH (
SfkpgAcct NVARCHAR(MAX) 'SfkpgAcct'
, AcctHldr_LglPrsn_NmAndAdr_Nm NVARCHAR(MAX) 'AcctHldr/LglPrsn/NmAndAdr/Nm'
, AcctHldr_LglPrsn_NmAndAdr_Adr_AdrLine NVARCHAR(MAX) 'AcctHldr/LglPrsn/NmAndAdr/Adr/AdrLine'
, AcctHldr_LglPrsn_NmAndAdr_Adr_Ctry NVARCHAR(MAX) 'AcctHldr/LglPrsn/NmAndAdr/Adr/Ctry'
, AcctHldr_LglPrsn_LEI NVARCHAR(MAX) 'AcctHldr/LglPrsn/LEI'
, AcctHldr_LglPrsn_Ownrsh NVARCHAR(MAX) 'AcctHldr/LglPrsn/Ownrsh'
, ShrhldgBal_ShrhldgTp NVARCHAR(MAX) 'ShrhldgBal/ShrhldgTp'
, ShrhldgBal_Unit NVARCHAR(MAX) 'ShrhldgBal/Unit'
)
--SfkpgAcct AcctHldr_LglPrsn_NmAndAdr_Nm AcctHldr_LglPrsn_NmAndAdr_Adr_AdrLine AcctHldr_LglPrsn_NmAndAdr_Adr_Ctry AcctHldr_LglPrsn_LEI AcctHldr_LglPrsn_Ownrsh ShrhldgBal_ShrhldgTp ShrhldgBal_Unit
--450812361 Foo 1 CORPORATE WAY, New York 15951 US 5493231HPIWHJS5QL7N39 OWNR BENE 1000
--450812362 Bar 2 CORPORATE WAY US 5493231HP2342345QL7N39 OWNR BENE 300
有时也有多个 AdrLine 字段,但是在与上述相同的示例中,我不知道谁来 go 备份链以引用任何以前的值,以便我可以加入。
SELECT *
FROM OPENXML(@hDoc,'message/Body/SfkpgAcctAndHldgs/AcctSubLvl/Dsclsr/AcctHldr/LglPrsn/NmAndAdr/Adr/AdrLine') WITH (
AcctHldr_LglPrsn_NmAndAdr_Adr_AdrLine NVARCHAR(MAX) '.'
)
--AcctHldr_LglPrsn_NmAndAdr_Adr_AdrLine
--1 CORPORATE WAY, New York 15951
--2 CORPORATE WAY
--New York
--15951
EXEC sp_xml_removedocument @hDoc
理想情况下,我想要一个平面文件中的所有值,我可以使用视图将各个表连接在一起,前提是我可以赋予现有 ID 或生成新 ID。
--SfkpgAcct DsclsrSfkpgAcct Nm AdrLine1 AdrLine2 AdrLine3 Ctry LEI Ownrsh ShrhldgTp Unit
--UHS5465 450812361 Foo 1 CORPORATE WAY, New York 15951 US 5493231HPIWHJS5QL7N39 OWNR BENE 1000
--UHS5465 450812362 Bar 2 CORPORATE WAY New York 15951 US 5493231HP2342345QL7N39 OWNR BENE 300
保留 Microsoft 专有的OPENXML()
及其伙伴sp_xml_preparedocument
和sp_xml_removedocument
只是为了与过时的 SQL Server 2000 向后兼容。它们的使用减少到很少的边缘情况。 从 SQL Server 2005 开始,强烈建议重新编写您的 SQL 并将其切换到 XQuery。
SQL
DECLARE @xml XML =
N'<Message>
<Body>
<SfkpgAcctAndHldgs>
<SfkpgAcct>UHS5465</SfkpgAcct>
<AcctSubLvl>
<Dsclsr>
<SfkpgAcct>450812361</SfkpgAcct>
<AcctHldr>
<LglPrsn>
<NmAndAdr>
<Nm>Foo</Nm>
<Adr>
<AdrLine>1 CORPORATE WAY, New York 15951</AdrLine>
<Ctry>US</Ctry>
</Adr>
</NmAndAdr>
<LEI>5493231HPIWHJS5QL7N39</LEI>
<Ownrsh>OWNR</Ownrsh>
</LglPrsn>
</AcctHldr>
<ShrhldgBal>
<ShrhldgTp>BENE</ShrhldgTp>
<Unit>1000</Unit>
</ShrhldgBal>
</Dsclsr>
<Dsclsr>
<SfkpgAcct>450812362</SfkpgAcct>
<AcctHldr>
<LglPrsn>
<NmAndAdr>
<Nm>Bar</Nm>
<Adr>
<AdrLine>2 CORPORATE WAY</AdrLine>
<AdrLine>New York</AdrLine>
<AdrLine>15951</AdrLine>
<Ctry>US</Ctry>
</Adr>
</NmAndAdr>
<LEI>5493231HP2342345QL7N39</LEI>
<Ownrsh>OWNR</Ownrsh>
</LglPrsn>
</AcctHldr>
<ShrhldgBal>
<ShrhldgTp>BENE</ShrhldgTp>
<Unit>300</Unit>
</ShrhldgBal>
</Dsclsr>
</AcctSubLvl>
</SfkpgAcctAndHldgs>
</Body>
</Message>';
SELECT c.value('(SfkpgAcct/text())[1]', 'VARCHAR(20)') AS SfkpgAcct
, x.value('(SfkpgAcct/text())[1]', 'VARCHAR(20)') AS DsclsrSfkpgAcct
, x.value('(AcctHldr/LglPrsn/NmAndAdr/Nm/text())[1]', 'VARCHAR(20)') AS Nm
, x.value('(AcctHldr/LglPrsn/NmAndAdr/Adr/AdrLine[1]/text())[1]', 'VARCHAR(50)') AS AdrLine1
, x.value('(AcctHldr/LglPrsn/NmAndAdr/Adr/AdrLine[2]/text())[1]', 'VARCHAR(50)') AS AdrLine2
, x.value('(AcctHldr/LglPrsn/NmAndAdr/Adr/AdrLine[3]/text())[1]', 'VARCHAR(50)') AS AdrLine3
, x.value('(AcctHldr/LglPrsn/NmAndAdr/Adr/Ctry/text())[1]', 'VARCHAR(50)') AS Ctry
, x.value('(AcctHldr/LglPrsn/LEI/text())[1]', 'VARCHAR(50)') AS LEI
, x.value('(AcctHldr/LglPrsn/Ownrsh/text())[1]', 'VARCHAR(50)') AS Ownrsh
, x.value('(ShrhldgBal/ShrhldgTp/text())[1]', 'VARCHAR(50)') AS ShrhldgTp
, x.value('(ShrhldgBal/Unit/text())[1]', 'VARCHAR(50)') AS Unit
FROM @xml.nodes('/Message/Body/SfkpgAcctAndHldgs') AS t1(c)
CROSS APPLY t1.c.nodes('AcctSubLvl/Dsclsr') AS t2(x);
Output
+-----------+-----------------+-----+---------------------------------+----------+----------+------+------------------------+--------+-----------+------+
| SfkpgAcct | DsclsrSfkpgAcct | Nm | AdrLine1 | AdrLine2 | AdrLine3 | Ctry | LEI | Ownrsh | ShrhldgTp | Unit |
+-----------+-----------------+-----+---------------------------------+----------+----------+------+------------------------+--------+-----------+------+
| UHS5465 | 450812361 | Foo | 1 CORPORATE WAY, New York 15951 | NULL | NULL | US | 5493231HPIWHJS5QL7N39 | OWNR | BENE | 1000 |
| UHS5465 | 450812362 | Bar | 2 CORPORATE WAY | New York | 15951 | US | 5493231HP2342345QL7N39 | OWNR | BENE | 300 |
+-----------+-----------------+-----+---------------------------------+----------+----------+------+------------------------+--------+-----------+------+
在 MS SQL 服务器中处理 XML 是一件痛苦的事情……恕我直言。 反正:
SELECT SfkpgAcct,
Dsclsr_SfkpgAcct,
Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Nm,
Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Adr_AdrLine1,
Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Adr_AdrLine2,
Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Adr_AdrLine3,
Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Adr_Ctry,
Dsclsr_AcctHldr_LglPrsn_LEI,
Dsclsr_AcctHldr_LglPrsn_Ownrsh,
Dsclsr_ShrhldgBal_ShrhldgTp,
Dsclsr_ShrhldgBal_Unit
FROM
OPENXML(@hDoc, 'message/Body/SfkpgAcctAndHldgs')
WITH
(
SfkpgAcct NVARCHAR(MAX) 'SfkpgAcct',
AcctSubLvl XML 'AcctSubLvl'
) t1
CROSS APPLY
(
SELECT item.row.value('SfkpgAcct[1]', 'nvarchar(max)'),
item.row.value('AcctHldr[1]/LglPrsn[1]/NmAndAdr[1]/Nm[1]', 'nvarchar(max)'),
item.row.value('AcctHldr[1]/LglPrsn[1]/NmAndAdr[1]/Adr[1]/AdrLine[1]', 'nvarchar(max)'),
item.row.value('AcctHldr[1]/LglPrsn[1]/NmAndAdr[1]/Adr[1]/AdrLine[2]', 'nvarchar(max)'),
item.row.value('AcctHldr[1]/LglPrsn[1]/NmAndAdr[1]/Adr[1]/AdrLine[3]', 'nvarchar(max)'),
item.row.value('AcctHldr[1]/LglPrsn[1]/NmAndAdr[1]/Adr[1]/Ctry[1]', 'nvarchar(max)'),
item.row.value('AcctHldr[1]/LglPrsn[1]/LEI[1]', 'nvarchar(max)'),
item.row.value('AcctHldr[1]/LglPrsn[1]/Ownrsh[1]', 'nvarchar(max)'),
item.row.value('ShrhldgBal[1]/ShrhldgTp[1]', 'nvarchar(max)'),
item.row.value('ShrhldgBal[1]/Unit[1]', 'nvarchar(max)')
FROM t1.AcctSubLvl.nodes('AcctSubLvl/Dsclsr') item(row)
) AS nodes(Dsclsr_SfkpgAcct
, Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Nm
, Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Adr_AdrLine1
, Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Adr_AdrLine2
, Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Adr_AdrLine3
, Dsclsr_AcctHldr_LglPrsn_NmAndAdr_Adr_Ctry
, Dsclsr_AcctHldr_LglPrsn_LEI
, Dsclsr_AcctHldr_LglPrsn_Ownrsh
, Dsclsr_ShrhldgBal_ShrhldgTp
, Dsclsr_ShrhldgBal_Unit);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.