几个问题插入和过滤 XML 数据到 SQL

Few issues Inserting and filtering XML data to SQL

我在将数据从 XML 文件插入到 SQL 服务器数据库时遇到了一些问题。

  1. 如何动态获取文件名?该文件每次都以不同的编号放在该路径上,但始终以 Idoc 开头,并且它是一个 .xml 文件。我在 OPENROWSET.

    中设置变量时遇到问题
  2. 目前我只从一条路径 (ZPROD) 获取数据,但我希望能够从 EDI_DC40/DOCNUM 而不是 ZPROD/PLN_ORDER 插入数据,我会需要另一个 CROSS APPLY,但我无法让它工作。

  3. 我想忽略 QTY 中的 .000,我尝试将其设置为 int 但没有用,“无法转换为 int”。

  4. 有没有什么办法可以忽略LINENO的大部分,只获取最后两个字符?它设置为 varchar(2) 但显然是前两个字符,而不是最后一个。

下面是我的代码,希望一切都在规则之内并且可以理解:

谢谢。

<?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>
CREATE TABLE XMLTESTTABLE
(
    PONo int, 
    ASP int, 
    LOTNo varchar(11), 
    EntryDate date, 
    StartDate date, 
    EndDate date, 
    GAS int, 
    PlannedQty varchar(15), 
    LineNum varchar(2), 
    SAPDesc varchar(200), 
    StartTime date, 
    EndTime date
);
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(2)'),
   MY_XML.ZPROD.query('MAKTX').value('.', 'VARCHAR(200)'),
   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);

请尝试以下解决方案。

  • 无需使用.query()方法。
  • ##3,4 已解决。
  • 我冒昧地将无效的 240000 次处理为 23:59:59。
  • 最后两列的数据类型是time(0)

SQL

USE tempdb;
GO

DROP TABLE IF EXISTS XMLTESTTABLE;

CREATE TABLE XMLTESTTABLE (
    PONo INT, 
    ASP int, 
    LOTNo varchar(11), 
    EntryDate date, 
    StartDate date, 
    EndDate date, 
    GAS int, 
    PlannedQty varchar(15), 
    LineNum varchar(2), 
    SAPDesc varchar(200), 
    StartTime time(0), 
    EndTime time(0)
);

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]', 'DECIMAL(10,0)') AS [qty]
    , RIGHT(ZPROD.value('(LINENO/text())[1]', 'VARCHAR(10)'), 2) AS [lineno]
    , ZPROD.value('(MAKTX/text())[1]', 'VARCHAR(200)') AS MAKTX
    , TRY_CAST(STUFF(STUFF(ZPROD.value('(START2/text())[1]', 'CHAR(6)'),3,0,':'),6,0,':') AS TIME)
    , TRY_CAST(IIF(STUFF(STUFF(ZPROD.value('(END2/text())[1]', 'CHAR(6)'),3,0,':'),6,0,':')='24:00:00'
        ,'23:59:59',null) AS TIME)
FROM (SELECT TRY_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);

-- test
SELECT * FROM dbo.XMLTESTTABLE;