SQL : 如何在新节点中动态获取多个 XML 父节点值?
SQL : How to get multiple XML parent node values inside new node dynamically?
如何动态获得所需的输出?
在源代码中 XML 我有多个用于 SHIPMENTS 的子节点。我需要从它们那里获取部分信息并将它们映射到 SQL 内的新输出(我使用 SSMS)。
我只需要输出 shipmentno、tripsequence、unloaddate 和 unloadtime - 但对于多次发货。
来源XML:
<SHIPMENTS>
<Laden>JAMAICA</Laden>
<CLIENT>FAKE CLIENT</CLIENT>
<Activiteit>SD</Activiteit>
<TRIPSEQUENCE>10</TRIPSEQUENCE>
<Tpttype>FRE</Tpttype>
<SHIPMENTNO>42069</SHIPMENTNO>
</SHIPMENTS>
<SHIPMENTS>
<Lossen>NEW ZEALANG</Lossen>
<CLIENT>FAKE CLIENT</CLIENT>
<Activiteit>DS</Activiteit>
<TRIPSEQUENCE>70</TRIPSEQUENCE>
<Tpttype>DEZ</Tpttype>
<SHIPMENTNO>42169</SHIPMENTNO>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
</SHIPMENTS>
<SHIPMENTS>
<Lossen>LONDON</Lossen>
<CLIENT>FAKE CLIENT</CLIENT>
<Activiteit>LO</Activiteit>
<TRIPSEQUENCE>80</TRIPSEQUENCE>
<Tpttype>DSZ</Tpttype>
<SHIPMENTNO>42269</SHIPMENTNO>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
</SHIPMENTS>
<SHIPMENTS>
<Lossen>LOUISIANA</Lossen>
<CLIENT>FAKE CLIENT</CLIENT>
<Activiteit>DS</Activiteit>
<TRIPSEQUENCE>90</TRIPSEQUENCE>
<Tpttype>GRO</Tpttype>
<SHIPMENTNO>42369</SHIPMENTNO>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
</SHIPMENTS>
<SHIPMENTS>
<Lossen>KOS</Lossen>
<CLIENT>FAKE CLIENT</CLIENT>
<Activiteit>LO</Activiteit>
<TRIPSEQUENCE>100</TRIPSEQUENCE>
<Tpttype>GFS</Tpttype>
<SHIPMENTNO>42369</SHIPMENTNO>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>08:00:00</UNLOADTIME>
</SHIPMENTS>
<SHIPMENTS>
<Lossen>ROTTERDAM</Lossen>
<CLIENT>FAKE CLIENT</CLIENT>
<Activiteit>LOL</Activiteit>
<TRIPSEQUENCE>110</TRIPSEQUENCE>
<Tpttype>GRO</Tpttype>
<SHIPMENTNO>42469</SHIPMENTNO>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
</SHIPMENTS>
<SHIPMENTS>
<Lossen>TENERIFE</Lossen>
<CLIENT>FAKE CLIENT</CLIENT>
<Activiteit>LO</Activiteit>
<TRIPSEQUENCE>120</TRIPSEQUENCE>
<Tpttype>GRO</Tpttype>
<SHIPMENTNO>42570</SHIPMENTNO>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
</SHIPMENTS>
MISSION : 在我的输出 XML 中,我需要 <SHIPMENTS/>
成为父节点,多个 <SHIPMENT/>
子节点包含值来自来源 XML。这是输出的样子
期望输出:
<SHIPMENTS>
<SHIPMENT>
<SHIPMENTNO>UI0010912</SHIPMENTNO>
<TRIPSEQUENCE>1</TRIPSEQUENCE>
<UNLOADDATE>20211012</UNLOADDATE>
<UNLOADTIME>10:00</UNLOADTIME>
</SHIPMENT>
<SHIPMENT>
<SHIPMENTNO>UI0010911</SHIPMENTNO>
<TRIPSEQUENCE>2</TRIPSEQUENCE>
<UNLOADDATE>20211012</UNLOADDATE>
<UNLOADTIME>11:00</UNLOADTIME>
</SHIPMENT>
<SHIPMENT>
<SHIPMENTNO>UI0010913</SHIPMENTNO>
<TRIPSEQUENCE>3</TRIPSEQUENCE>
<UNLOADDATE>20211012</UNLOADDATE>
<UNLOADTIME>15:00</UNLOADTIME>
</SHIPMENT>
</SHIPMENTS>
查询:
这是我需要的每个子节点的结构和值:
SET @xml = (
(SELECT
N'' AS [TRIP/SHIPMENTS],
N'' AS [TRIP/SHIPMENTS/SHIPMENT],
N'UI45048839' AS [TRIP/SHIPMENTS/SHIPMENT/SHIPMENTNO],
N'1' AS [TRIP/SHIPMENTS/SHIPMENT/TRIPSEQUENCE],
@XML.query(N'(/SHIPMENTS/UNLOADDATE)[5]').value('.', N'nvarchar(MAX)') AS [TRIP/SHIPMENTS/SHIPMENT/UNLOADDATE],
@XML.query(N'(/SHIPMENTS/UNLOADTIME)[5]').value('.', N'nvarchar(MAX)') AS [TRIP/SHIPMENTS/SHIPMENT/UNLOADTIME],
N'' AS [TRIP/SHIPMENTS/SHIPMENT],
N'UI45048841' AS [TRIP/SHIPMENTS/SHIPMENT/SHIPMENTNO],
N'2' AS [TRIP/SHIPMENTS/SHIPMENT/TRIPSEQUENCE],
@XML.query(N'(/SHIPMENTS/UNLOADDATE)[3]').value('.', N'nvarchar(MAX)') AS [TRIP/SHIPMENTS/SHIPMENT/UNLOADDATE],
@XML.query(N'(/SHIPMENTS/UNLOADTIME)[3]').value('.', N'nvarchar(MAX)') AS [TRIP/SHIPMENTS/SHIPMENT/UNLOADTIME],
N'UI45048840' AS [TRIP/SHIPMENTS/SHIPMENT/SHIPMENTNO],
N'3' AS [TRIP/SHIPMENTS/SHIPMENT/TRIPSEQUENCE],
@XML.query(N'(/SHIPMENTS/UNLOADDATE)[2]').value('.', N'nvarchar(MAX)') AS [TRIP/SHIPMENTS/SHIPMENT/UNLOADDATE],
@XML.query(N'(/SHIPMENTS/UNLOADTIME)[2]').value('.', N'nvarchar(MAX)') AS [TRIP/SHIPMENTS/SHIPMENT/UNLOADTIME]
FOR XML PATH (N'SHIPMENTS'), TYPE
) AS [SHIPMENTS/SHIPMENT]
FOR XML PATH(N''), ROOT(N'TRIPS'), TYPE
);
SELECT @xml AS [FileContent];
显然 RETURNS :
<SHIPMENTS>
<SHIPMENT>
<SHIPMENTNO>UI45048839</SHIPMENTNO>
<TRIPSEQUENCE>1</TRIPSEQUENCE>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
<SHIPMENTNO>UI45048841</SHIPMENTNO>
<TRIPSEQUENCE>2</TRIPSEQUENCE>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
<SHIPMENTNO>UI45048840</SHIPMENTNO>
<TRIPSEQUENCE>3</TRIPSEQUENCE>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
</SHIPMENT>
</SHIPMENTS>
我不喜欢我的方法,因为它主要是硬编码和重复结果。
如何动态获得所需的输出?
感谢您的宝贵时间!
看来你很over-complicating这个。您可以使用 .query()
生成包含正确节点
的构造 XML
SELECT @xml.query('
<SHIPMENTS>
{
for $s in /SHIPMENTS
return
<SHIPMENT>
{
$s/*[
local-name() = ("SHIPMENTNO", "TRIPSEQUENCE", "UNLOADDATE", "UNLOADTIME")
]
}
</SHIPMENT>
}
</SHIPMENTS>
');
- 这将创建一个新的根
SHIPMENTS
节点。
- 其中,它获取所有原始
SHIPMENTS
个节点并从中创建 SHIPMENT
个节点。
- 其中每一个只包含四个相关的子节点。它使用通配符获取所有节点,然后使用
local-name()
. 检查它们
如何动态获得所需的输出?
在源代码中 XML 我有多个用于 SHIPMENTS 的子节点。我需要从它们那里获取部分信息并将它们映射到 SQL 内的新输出(我使用 SSMS)。 我只需要输出 shipmentno、tripsequence、unloaddate 和 unloadtime - 但对于多次发货。
来源XML:
<SHIPMENTS>
<Laden>JAMAICA</Laden>
<CLIENT>FAKE CLIENT</CLIENT>
<Activiteit>SD</Activiteit>
<TRIPSEQUENCE>10</TRIPSEQUENCE>
<Tpttype>FRE</Tpttype>
<SHIPMENTNO>42069</SHIPMENTNO>
</SHIPMENTS>
<SHIPMENTS>
<Lossen>NEW ZEALANG</Lossen>
<CLIENT>FAKE CLIENT</CLIENT>
<Activiteit>DS</Activiteit>
<TRIPSEQUENCE>70</TRIPSEQUENCE>
<Tpttype>DEZ</Tpttype>
<SHIPMENTNO>42169</SHIPMENTNO>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
</SHIPMENTS>
<SHIPMENTS>
<Lossen>LONDON</Lossen>
<CLIENT>FAKE CLIENT</CLIENT>
<Activiteit>LO</Activiteit>
<TRIPSEQUENCE>80</TRIPSEQUENCE>
<Tpttype>DSZ</Tpttype>
<SHIPMENTNO>42269</SHIPMENTNO>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
</SHIPMENTS>
<SHIPMENTS>
<Lossen>LOUISIANA</Lossen>
<CLIENT>FAKE CLIENT</CLIENT>
<Activiteit>DS</Activiteit>
<TRIPSEQUENCE>90</TRIPSEQUENCE>
<Tpttype>GRO</Tpttype>
<SHIPMENTNO>42369</SHIPMENTNO>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
</SHIPMENTS>
<SHIPMENTS>
<Lossen>KOS</Lossen>
<CLIENT>FAKE CLIENT</CLIENT>
<Activiteit>LO</Activiteit>
<TRIPSEQUENCE>100</TRIPSEQUENCE>
<Tpttype>GFS</Tpttype>
<SHIPMENTNO>42369</SHIPMENTNO>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>08:00:00</UNLOADTIME>
</SHIPMENTS>
<SHIPMENTS>
<Lossen>ROTTERDAM</Lossen>
<CLIENT>FAKE CLIENT</CLIENT>
<Activiteit>LOL</Activiteit>
<TRIPSEQUENCE>110</TRIPSEQUENCE>
<Tpttype>GRO</Tpttype>
<SHIPMENTNO>42469</SHIPMENTNO>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
</SHIPMENTS>
<SHIPMENTS>
<Lossen>TENERIFE</Lossen>
<CLIENT>FAKE CLIENT</CLIENT>
<Activiteit>LO</Activiteit>
<TRIPSEQUENCE>120</TRIPSEQUENCE>
<Tpttype>GRO</Tpttype>
<SHIPMENTNO>42570</SHIPMENTNO>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
</SHIPMENTS>
MISSION : 在我的输出 XML 中,我需要 <SHIPMENTS/>
成为父节点,多个 <SHIPMENT/>
子节点包含值来自来源 XML。这是输出的样子
期望输出:
<SHIPMENTS>
<SHIPMENT>
<SHIPMENTNO>UI0010912</SHIPMENTNO>
<TRIPSEQUENCE>1</TRIPSEQUENCE>
<UNLOADDATE>20211012</UNLOADDATE>
<UNLOADTIME>10:00</UNLOADTIME>
</SHIPMENT>
<SHIPMENT>
<SHIPMENTNO>UI0010911</SHIPMENTNO>
<TRIPSEQUENCE>2</TRIPSEQUENCE>
<UNLOADDATE>20211012</UNLOADDATE>
<UNLOADTIME>11:00</UNLOADTIME>
</SHIPMENT>
<SHIPMENT>
<SHIPMENTNO>UI0010913</SHIPMENTNO>
<TRIPSEQUENCE>3</TRIPSEQUENCE>
<UNLOADDATE>20211012</UNLOADDATE>
<UNLOADTIME>15:00</UNLOADTIME>
</SHIPMENT>
</SHIPMENTS>
查询: 这是我需要的每个子节点的结构和值:
SET @xml = (
(SELECT
N'' AS [TRIP/SHIPMENTS],
N'' AS [TRIP/SHIPMENTS/SHIPMENT],
N'UI45048839' AS [TRIP/SHIPMENTS/SHIPMENT/SHIPMENTNO],
N'1' AS [TRIP/SHIPMENTS/SHIPMENT/TRIPSEQUENCE],
@XML.query(N'(/SHIPMENTS/UNLOADDATE)[5]').value('.', N'nvarchar(MAX)') AS [TRIP/SHIPMENTS/SHIPMENT/UNLOADDATE],
@XML.query(N'(/SHIPMENTS/UNLOADTIME)[5]').value('.', N'nvarchar(MAX)') AS [TRIP/SHIPMENTS/SHIPMENT/UNLOADTIME],
N'' AS [TRIP/SHIPMENTS/SHIPMENT],
N'UI45048841' AS [TRIP/SHIPMENTS/SHIPMENT/SHIPMENTNO],
N'2' AS [TRIP/SHIPMENTS/SHIPMENT/TRIPSEQUENCE],
@XML.query(N'(/SHIPMENTS/UNLOADDATE)[3]').value('.', N'nvarchar(MAX)') AS [TRIP/SHIPMENTS/SHIPMENT/UNLOADDATE],
@XML.query(N'(/SHIPMENTS/UNLOADTIME)[3]').value('.', N'nvarchar(MAX)') AS [TRIP/SHIPMENTS/SHIPMENT/UNLOADTIME],
N'UI45048840' AS [TRIP/SHIPMENTS/SHIPMENT/SHIPMENTNO],
N'3' AS [TRIP/SHIPMENTS/SHIPMENT/TRIPSEQUENCE],
@XML.query(N'(/SHIPMENTS/UNLOADDATE)[2]').value('.', N'nvarchar(MAX)') AS [TRIP/SHIPMENTS/SHIPMENT/UNLOADDATE],
@XML.query(N'(/SHIPMENTS/UNLOADTIME)[2]').value('.', N'nvarchar(MAX)') AS [TRIP/SHIPMENTS/SHIPMENT/UNLOADTIME]
FOR XML PATH (N'SHIPMENTS'), TYPE
) AS [SHIPMENTS/SHIPMENT]
FOR XML PATH(N''), ROOT(N'TRIPS'), TYPE
);
SELECT @xml AS [FileContent];
显然 RETURNS :
<SHIPMENTS>
<SHIPMENT>
<SHIPMENTNO>UI45048839</SHIPMENTNO>
<TRIPSEQUENCE>1</TRIPSEQUENCE>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
<SHIPMENTNO>UI45048841</SHIPMENTNO>
<TRIPSEQUENCE>2</TRIPSEQUENCE>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
<SHIPMENTNO>UI45048840</SHIPMENTNO>
<TRIPSEQUENCE>3</TRIPSEQUENCE>
<UNLOADDATE>15/12</UNLOADDATE>
<UNLOADTIME>09:00:00</UNLOADTIME>
</SHIPMENT>
</SHIPMENTS>
我不喜欢我的方法,因为它主要是硬编码和重复结果。
如何动态获得所需的输出?
感谢您的宝贵时间!
看来你很over-complicating这个。您可以使用 .query()
生成包含正确节点
SELECT @xml.query('
<SHIPMENTS>
{
for $s in /SHIPMENTS
return
<SHIPMENT>
{
$s/*[
local-name() = ("SHIPMENTNO", "TRIPSEQUENCE", "UNLOADDATE", "UNLOADTIME")
]
}
</SHIPMENT>
}
</SHIPMENTS>
');
- 这将创建一个新的根
SHIPMENTS
节点。 - 其中,它获取所有原始
SHIPMENTS
个节点并从中创建SHIPMENT
个节点。 - 其中每一个只包含四个相关的子节点。它使用通配符获取所有节点,然后使用
local-name()
. 检查它们