使用 CROSS APPLY 从 XML 到 MSSQL 的数据

Data from XML to MSSQL using CROSS APPLY

我在使用 CROSS APPLY 将一些数据从 XML 文件提取到 MSSQL 数据库时遇到问题,这是我所拥有的:

注意:我确实在此处阅读了有关如何 post 的信息,但如果我仍然错了,请原谅我。

XML 文件:

<?xml version="1.0" encoding="UTF-8" ?>
<ZMPROD01>
   <IDOC BEGIN="1">
      <EDI_DC40 SEGMENT="1">
         <TABNAM>EDI_DC40</TABNAM>
         <DOCNUM>0000003899888135</DOCNUM>
         <CREDAT>20220201</CREDAT>
         <CRETIM>152041</CRETIM>
      </EDI_DC40>
      <ZPROD SEGMENT="1">
         <WERKS>8285</WERKS>
         <LGNUM>0</LGNUM>
         <AUFNR>000915229446</AUFNR>
         <LINENO>RM01PL01</LINENO>
         <CHARG>0006186588</CHARG>
         <START1>20220202</START1>
         <START2>211609</START2>
         <QTY>4166.000</QTY>
         <END1>20220202</END1>
         <END2>240000</END2>
         <MAKTX>579 FUS5 75ML ULTRA SENST GEL</MAKTX>
         <PLN_ORDER>6963701111</PLN_ORDER>
         <Z1PRODI SEGMENT="1">
            <POSNR>000010</POSNR>
            <MATNR>000000000098920665</MATNR>
         </Z1PRODI>
         <Z1PRODI SEGMENT="1">
            <POSNR>000040</POSNR>
            <HRKFT>V010</HRKFT>
         </Z1PRODI>
         <Z1PRODI SEGMENT="1">
            <POSNR>000050</POSNR>
            <MATNR>000000000099396964</MATNR>
         </Z1PRODI>
      </ZPROD>
   </IDOC>
</ZMPROD01>

我的SQL查询:

INSERT INTO XMLTESTTABLE(PONo, ASP, LOTNo, EntryDate, StartDate, EndDate, GAS, PlannedQty, LineNum, SAPDesc, StartTime, EndTime)
SELECT
   MY_XML.ZPROD.query('AUFNR').value('.', 'VARCHAR(9)'),
   MY_XML.ZPROD.query('CHARG').value('.', 'VARCHAR(8)'),
   MY_XML.ZPROD.query('PLN_ORDER').value('.', 'VARCHAR(10)'),
   MY_XML.ZPROD.query('START1').value('.', 'date'),
   MY_XML.ZPROD.query('START1').value('.', 'date'),
   MY_XML.ZPROD.query('END1').value('.', 'date'),
   MY_XML.ZPROD.query('CHARG').value('.', 'VARCHAR(8)'),
   MY_XML.ZPROD.query('QTY').value('.', 'VARCHAR(9)'),
   MY_XML.ZPROD.query('LINENO').value('.', 'VARCHAR(1)'),
   MY_XML.ZPROD.query('MAKTX').value('.', 'VARCHAR(9)'),
   MY_XML.ZPROD.query('START2').value('.', 'time'),
   MY_XML.ZPROD.query('END2').value('.', 'time')
FROM (SELECT CAST(MY_XML AS xml)
      FROM OPENROWSET(BULK 'C:\Users\PC_user\Documents\Idoc3899888135.xml', SINGLE_BLOB) AS T(MY_XML)) AS T(MY_XML)
      CROSS APPLY MY_XML.nodes('ZMPROD01/ZPROD') AS MY_XML (ZPROD);

我得到的结果是(0 行受影响)。我尝试多次替换 ZMPROD01/ZPROD 但出现了不同的错误,有时会抱怨无法转换为日期数据类型。

在单独的注释中,我也可以从 EDI_DC40 获取数据吗?不确定 CROSS APPLY 在文档中查找不同位置时的样子。

感谢您的帮助。

谢谢。

您的路径似乎不对 - 怎么样:

CROSS APPLY MY_XML.nodes('ZMPROD01/IDOC/ZPROD') AS MY_XML (ZPROD);

你好像忘记了IDOC

而数据类型是因为你无法将时间转换为时间数据类型。尝试从 select 开始,所有内容都转换为 varchar,然后开始更改数据类型,您会发现错误

SELECT CAST('211609' AS TIME)

returns错误

请尝试以下解决方案。

要点:

  • 我调整了 .nodes() 方法中的 XPath 表达式。
  • 无需使用.query()方法。
  • text() 是出于性能原因添加的。
  • 最后两个数据元素转换为 TIME 数据类型。
  • 如前所述,<END2>240000</END2> 不是合法的 TIME 数据类型的值。

SQL

--INSERT INTO XMLTESTTABLE(PONo, ASP, LOTNo, EntryDate, StartDate, EndDate, GAS, PlannedQty, LineNum, SAPDesc, StartTime, EndTime)
SELECT ZPROD.value('(AUFNR/text())[1]', 'VARCHAR(9)')
    , ZPROD.value('(CHARG/text())[1]', 'VARCHAR(8)')
    , ZPROD.value('(PLN_ORDER/text())[1]', 'VARCHAR(10)')
    , ZPROD.value('(START1/text())[1]', 'date')
    , ZPROD.value('(START1/text())[1]', 'date')
    , ZPROD.value('(END1/text())[1]', 'date')
    , ZPROD.value('(CHARG/text())[1]', 'VARCHAR(8)')
    , ZPROD.value('(QTY/text())[1]', 'VARCHAR(9)')
    , ZPROD.value('(LINENO/text())[1]', 'VARCHAR(1)')
    , ZPROD.value('(MAKTX/text())[1]', 'VARCHAR(9)')
    , TRY_CAST(STUFF(STUFF(ZPROD.value('(START2/text())[1]', 'CHAR(6)'),3,0,':'),6,0,':') AS TIME)
    , TRY_CAST(STUFF(STUFF(ZPROD.value('(END2/text())[1]', 'CHAR(6)'),3,0,':'),6,0,':') AS TIME)
FROM (SELECT CAST(MY_XML AS xml)
      FROM OPENROWSET(BULK 'e:\Temp\Idoc3899888135.xml', SINGLE_BLOB) AS T(MY_XML)) AS T(MY_XML)
      CROSS APPLY MY_XML.nodes('/ZMPROD01/IDOC/ZPROD') AS MY_XML (ZPROD);