将 XML 数据上传到 SQL Server

Posted

技术标签:

【中文标题】将 XML 数据上传到 SQL Server【英文标题】:Uploading XML data into SQL Server 【发布时间】:2021-12-02 03:50:16 【问题描述】:

这对我来说是一项新任务,过去一周我读了很多关于 OPENXML、xpath 和各种有趣的东西,但我仍在努力将这些 XML 数据推送到我的数据库中。我不能共享 XML 数据,因为它很敏感,但它大部分都是元素,有几个兄弟节点和几个子节点。这是我的代码:

SELECT DISTINCT
   MY_XML.Inspection.query('inspectionId').value('.', 'INT'),
   MY_XML.Inspection.query('InspReportID').value('.', 'VARCHAR(50)'),
   MY_XML.Inspection.query('InspectionPostDate').value('.', 'DATE'),
   MY_XML.Inspection.query('InspStartDate').value('.', 'DATE'),
   MY_XML.Inspection.query('InspStartTime').value('.', 'INT'),
   MY_XML.Inspection.query('InspEndTime').value('.', 'INT'),
   MY_XML.Inspection.query('InspectionLevelId').value('.', 'INT'),
   MY_XML.Inspection.query('InspectionLevelDesc').value('.', 'VARCHAR(50)'),
   MY_XML.Inspection.query('PostAccidentIndicator').value('.', 'VARCHAR(20)'),
   Location.L.query('InspLocationCode').value('.', 'VARCHAR(50)'),
   Location.L.query('InspLocationText').value('.', 'VARCHAR(50)'),
   Violations.V.query('InspTotalOOSVioNum').value('.', 'INT'),
   Driver.D.query('DriverLastName').value('.','VARCHAR(100)')

FROM (SELECT CAST(MY_XML AS xml)
      FROM OPENROWSET(BULK 'C:\InspectionXML2.xml', SINGLE_BLOB) AS T(MY_XML)) AS T(MY_XML)
      OUTER APPLY MY_XML.nodes('Inspections/Inspection/InspMain') AS MY_XML (Inspection)
      OUTER APPLY MY_XML.nodes('Inspections/Inspection/InspMain/InspLocation') AS Location (L)
      OUTER APPLY MY_XML.nodes('Inspections/Inspection/InspMain/InspTotalCounts') AS Violations (V)
      OUTER APPLY MY_XML.nodes('Inspections/Inspection/Drivers/Driver') AS Driver (D)
ORDER BY 1;

此代码非常适合上传一个检查,但我需要上传几个,并且数据混合和匹配都错了!请帮忙,我对新方法持开放态度。我正在研究自动转换器,所以请帮忙!

1)

<?xml version="1.0"?>
-<Inspections schemaVersionCode="2.3" sourceSystemCode="COMPASS">
-<Inspection>
-<InspMain>
<inspectionId>123</inspectionId>
<InspReportID>OH-123</InspReportID>
<InspectionPostDate>10/07/2021</InspectionPostDate>
<InspStartDate>10/07/2021</InspStartDate>
<InspStartTime>0945</InspStartTime>
<InspEndTime>1200</InspEndTime>
<InspectionLevelId>1</InspectionLevelId>
<InspectionLevelDesc>FULL</InspectionLevelDesc>
<PostAccidentIndicator>NO</PostAccidentIndicator>
-<InspLocation>
<InspLocationCode>FIXED SITE</InspLocationCode>
<InspLocationText>CAMBRIDGES</InspLocationText>
</InspLocation>
<InspHazmatTypeCode/>
-<InspTotalCounts>
<InspTotalOOSVioNum>2</InspTotalOOSVioNum>
</InspTotalCounts>
</InspMain>
-<Drivers>
-<Driver>
<DriverLastName>RODNEY</DriverLastName>
<DriverBirthDate>12/31/1900</DriverBirthDate>
<DriverLicenseID>123</DriverLicenseID>
<DriverLicenseStateCode>OH</DriverLicenseStateCode>
</Driver>
</Drivers>
-<Vehicles>
-<Vehicle>
<VehicleUnitNum>1</VehicleUnitNum>
<VehicleUnitTypeCode>TRUCK TRACTOR</VehicleUnitTypeCode>
<VehicleMakeCode>INTL</VehicleMakeCode>
<VehicleCompanyID>123</VehicleCompanyID>
<VehicleLicenseID>AG123</VehicleLicenseID>
<VehicleLicenseStateCode>PA</VehicleLicenseStateCode>
<IEPDotNumber/>
</Vehicle>
-<Vehicle>
<VehicleUnitNum>2</VehicleUnitNum>
<VehicleUnitTypeCode>SEMI-TRAILER</VehicleUnitTypeCode>
<VehicleMakeCode>TRLK</VehicleMakeCode>
<VehicleCompanyID>1234</VehicleCompanyID>
<VehicleLicenseID>1234</VehicleLicenseID>
<VehicleLicenseStateCode>OK</VehicleLicenseStateCode>
<IEPDotNumber/>
</Vehicle>
</Vehicles>
-<Violations>
-<Violation>
<VioseqID>5</VioSeqID>
<VioRegSectionCode>NO</VioRegSectionCode>
<VioDescText>NO</VioDescText>
<VioOOSFlag>YES</VioOOSFlag>
<VehicleUnitCode>D</VehicleUnitCode>
<ViolPartSection>395.8(a)(1)</ViolPartSection>
<StateCitationNumber/>
<ViolationCategory>NO LOG BOOK,LOG NOT CURRENT,GENERAL LOG VIOLATIONS</ViolationCategory>
<SectionDesc>ELD - No record of duty status (ELD Required)</SectionDesc>
<IEPAttrFlag/>
<StateCitationResult>N/A</StateCitationResult>
</Violation>
-<Violation>
<VioSeqID>1</VioSeqID>
<VioRegSectionCode>NO</VioRegSectionCode>
<VioDescText>NO</VioDescText>
<VioOOSFlag>NO</VioOOSFlag>
<VehicleUnitCode>D</VehicleUnitCode>
<ViolPartSection>392.2</ViolPartSection>
<StateCitationNumber/>
<ViolationCategory>ALL OTHER DRIVER VIOLATIONS</ViolationCategory>
<SectionDesc>Miscellaneous Traffic Law Violation</SectionDesc>
<IEPAttrFlag/>
<StateCitationResult>N/A</StateCitationResult>
</Violation>
-<Violation>
<VioSeqID>3</VioSeqID>
<VioRegSectionCode>NO</VioRegSectionCode>
<VioDescText>NO</VioDescText>
<VioOOSFlag>NO</VioOOSFlag>
<VehicleUnitCode>1</VehicleUnitCode>
<ViolPartSection>393.45(d)</ViolPartSection>
<StateCitationNumber/>
<ViolationCategory>BRAKES, ALL OTHERS</ViolationCategory>
<SectionDesc>Brake Connections with Leaks Under Vehicle</SectionDesc>
<IEPAttrFlag/>
<StateCitationResult>N/A</StateCitationResult>
</Violation>
-<Violation>
<VioSeqID>2</VioSeqID>
<VioRegSectionCode>NO</VioRegSectionCode>
<VioDescText>NO</VioDescText>
<VioOOSFlag>NO</VioOOSFlag>
<VehicleUnitCode>1</VehicleUnitCode>
<ViolPartSection>393.45(d)</ViolPartSection>
<StateCitationNumber/>
<ViolationCategory>BRAKES, ALL OTHERS</ViolationCategory>
<SectionDesc>Brake Connections with Leaks - Connection to Power Unit</SectionDesc>
<IEPAttrFlag/>
<StateCitationResult>N/A</StateCitationResult>
</Violation>
-<Violation>
<VioSeqID>4</VioSeqID>
<VioRegSectionCode/>
<VioDescText>NO</VioDescText>
<VioOOSFlag>YES</VioOOSFlag>
<VehicleUnitCode>1</VehicleUnitCode>
<ViolPartSection>396.3(a)(1)</ViolPartSection>
<StateCitationNumber/>
<ViolationCategory>BRAKES, ALL OTHERS</ViolationCategory>
<SectionDesc>Brake system pressure loss</SectionDesc>
<IEPAttrFlag/>
<StateCitationResult>N/A</StateCitationResult>
</Violation>
-<Violation>
<VioSeqID>6</VioSeqID>
<VioRegSectionCode>NO</VioRegSectionCode>
<VioDescText>NO</VioDescText>
<VioOOSFlag>NO</VioOOSFlag>
<VehicleUnitCode>1</VehicleUnitCode>
<ViolPartSection>393.9(a)</ViolPartSection>
<StateCitationNumber/>
<ViolationCategory>LIGHTING</ViolationCategory>
<SectionDesc>Inoperative turn signal</SectionDesc>
<IEPAttrFlag/>
<StateCitationResult>N/A</StateCitationResult>
</Violation>
</Violations>
<StatusCode>YES</StatusCode>
</Inspection>
-<Inspection>
-<InspMain>
<inspectionId>12345</inspectionId>
<InspReportID>NC-1234</InspReportID>
<InspectionPostDate>10/08/2021</InspectionPostDate>
<InspStartDate>10/08/2021</InspStartDate>
<InspStartTime>0800</InspStartTime>
<InspEndTime>0900</InspEndTime>
<InspectionLevelId>3</InspectionLevelId>
<InspectionLevelDesc>DRIVER-ONLY</InspectionLevelDesc>
<PostAccidentIndicator>NO</PostAccidentIndicator>
-<InspLocation>
<InspLocationCode>ROADSIDE</InspLocationCode>
<InspLocationText>GOLden</InspLocationText>
</InspLocation>
<InspHazmatTypeCode/>
-<InspTotalCounts>
<InspTotalOOSVioNum>0</InspTotalOOSVioNum>
</InspTotalCounts>
</InspMain>
-<Drivers>
-<Driver>
<DriverLastName>joe schmoe</DriverLastName>
<DriverBirthDate>05/05/1888</DriverBirthDate>
<DriverLicenseID>1234</DriverLicenseID>
<DriverLicenseStateCode>FL</DriverLicenseStateCode>
</Driver>
</Drivers>
-<Vehicles>
-<Vehicle>
<VehicleUnitNum>1</VehicleUnitNum>
<VehicleUnitTypeCode>TRUCK TRACTOR</VehicleUnitTypeCode>
<VehicleMakeCode>PTRB</VehicleMakeCode>
<VehicleCompanyID>1234</VehicleCompanyID>
<VehicleLicenseID>1234</VehicleLicenseID>
<VehicleLicenseStateCode>TX</VehicleLicenseStateCode>
<IEPDotNumber/>
</Vehicle>
-<Vehicle>
<VehicleUnitNum>2</VehicleUnitNum>
<VehicleUnitTypeCode>SEMI-TRAILER</VehicleUnitTypeCode>
<VehicleMakeCode>FONA</VehicleMakeCode>
<VehicleCompanyID>1234</VehicleCompanyID>
<VehicleLicenseID>1234</VehicleLicenseID>
<VehicleLicenseStateCode>TX</VehicleLicenseStateCode>
<IEPDotNumber/>
</Vehicle>
</Vehicles>
-<Violations>
-<Violation>
<VioSeqID>1</VioSeqID>
<VioRegSectionCode>NO</VioRegSectionCode>
<VioDescText>NO</VioDescText>
<VioOOSFlag>NO</VioOOSFlag>
<VehicleUnitCode>D</VehicleUnitCode>
<ViolPartSection>392.2</ViolPartSection>
<StateCitationNumber/>
<ViolationCategory>FAILURE TO OBEY TRAFFIC CONTROL DEVICE</ViolationCategory>
<SectionDesc>Failure to obey traffic control device</SectionDesc>
<IEPAttrFlag/>
<StateCitationResult>N/A</StateCitationResult>
</Violation>
</Violations>
<StatusCode>NO</StatusCode>
</Inspection>
</Inspections>

2) 将检查上传到数据库 3)每次检查一排,无错配 4) SQL Server 2016

【问题讨论】:

提问时,您需要提供minimal reproducible example: (1) DDL 和样本数据填充,即 CREATE 表和 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上述#1 中的样本数据。 (4) 您的 SQL Server 版本 (SELECT @@version;)。 请提供 (1) 您的目标表 DDL,(2) 带有混淆值的真实输入 XML。 目标表目前不是问题,只需选择即可,一旦结果看起来不错,我就可以构建表并插入数据。 (2) 即将推出。 XML 已启动!谢谢! 【参考方案1】:

请尝试以下解决方案。

SQL

WITH rs (xmlData) AS
(
   SELECT TRY_CAST(BulkColumn AS XML) 
   FROM OPENROWSET(BULK N'e:\Temp\InspectionXML2.xml', SINGLE_BLOB) AS x
)
--INSERT INTO targetTable (...)
SELECT c.value('(InspMain/inspectionId/text())[1]', 'INT') AS inspectionId
    , c.value('(InspMain/InspReportID/text())[1]', 'VARCHAR(50)') AS InspReportID
    , c.value('(InspMain/InspectionPostDate/text())[1]', 'VARCHAR(20)') AS InspectionPostDate
    , c.value('(InspMain/InspStartDate/text())[1]', 'DATE') AS InspStartDate
    , c.value('(InspMain/InspStartTime/text())[1]', 'INT')AS InspStartTime
    , c.value('(InspMain/InspEndTime/text())[1]', 'INT') AS InspEndTime
    , c.value('(InspMain/InspectionLevelId/text())[1]', 'INT') AS InspectionLevelId
    , c.value('(InspMain/InspectionLevelDesc/text())[1]', 'VARCHAR(50)') AS InspectionLevelDesc
    , c.value('(InspMain/PostAccidentIndicator/text())[1]', 'VARCHAR(20)') AS PostAccidentIndicator
    , c.value('(InspMain/InspLocation/InspLocationCode/text())[1]', 'VARCHAR(50)') AS InspLocationCode
    , c.value('(InspMain/InspLocation/InspLocationText/text())[1]', 'VARCHAR(50)') AS InspLocationText
    , c.value('(InspMain/InspTotalCounts/InspTotalOOSVioNum/text())[1]', 'INT') AS InspTotalOOSVioNum
    , c.value('(Drivers/Driver/DriverLastName/text())[1]','VARCHAR(100)') AS DriverLastName
FROM rs 
   CROSS APPLY xmlData.nodes('/Inspections/Inspection') AS t(c);

输出

+--------------+--------------+--------------------+---------------+---------------+-------------+-------------------+---------------------+-----------------------+------------------+------------------+--------------------+----------------+
| inspectionId | InspReportID | InspectionPostDate | InspStartDate | InspStartTime | InspEndTime | InspectionLevelId | InspectionLevelDesc | PostAccidentIndicator | InspLocationCode | InspLocationText | InspTotalOOSVioNum | DriverLastName |
+--------------+--------------+--------------------+---------------+---------------+-------------+-------------------+---------------------+-----------------------+------------------+------------------+--------------------+----------------+
|          123 | OH123        | 10/07/2021         | 2021-10-07    |           945 |        1200 |                 1 | FULL                | NO                    | FIXED SITE       | CAMBRIDGES       |                  2 | RODNEY         |
|        12345 | NC1234       | 10/08/2021         | 2021-10-08    |           800 |         900 |                 3 | DRIVERONLY          | NO                    | ROADSIDE         | GOLden           |                  0 | joe schmoe     |
+--------------+--------------+--------------------+---------------+---------------+-------------+-------------------+---------------------+-----------------------+------------------+------------------+--------------------+----------------+

【讨论】:

这太棒了,干得好!非常感谢你,我很聪明,可以从这里推断其余的信不信由你,哈哈。标记为解决方案。保重,我希望宇宙用业力祝福你。

以上是关于将 XML 数据上传到 SQL Server的主要内容,如果未能解决你的问题,请参考以下文章

将数据从 webscraper 上传到 SQL server

将数据从 sql server 增量上传到 Amazon Redshift [关闭]

Winforms:如何使用 C# 将图片上传到 SQL Server 数据库

从C#中的数据中删除特殊字符后如何将dbf文件中的数百万行数据上传到SQL Server

将csv上传到sql server时,“给定的ColumnMapping与源或目标中的任何列都不匹配”

将csv上传到sql server时,“给定的ColumnMapping与源或目标中的任何列都不匹配”