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>
');

db<>fiddle

  • 这将创建一个新的根 SHIPMENTS 节点。
  • 其中,它获取所有原始 SHIPMENTS 个节点并从中创建 SHIPMENT 个节点。
  • 其中每一个只包含四个相关的子节点。它使用通配符获取所有节点,然后使用 local-name().
  • 检查它们