SQLXML 4 - 批量插入 xml 数据

Posted

技术标签:

【中文标题】SQLXML 4 - 批量插入 xml 数据【英文标题】:SQLXML 4 - Bulk insert of xml data 【发布时间】:2022-01-02 09:55:44 【问题描述】:

我有大约 2TB 以上的 XML 数据需要加载到 MSSQL DB 中(尽可能在最短的时间内)。问题是每个 XML 文件中的数据范围从 5MB 到 100MB,所有文本都在第一行。一个文件的第一行大约有 4400 万多个字符。

我编写了一个脚本来读取 XML 文件并填充数据库,目前它说大约需要 300 天来处理。我现在正在尝试 SQLXML 4.0。我使用 XmlSchemaInference 从多个 XML 文件生成 XSD。我使用 XSD2DB 工具从 XSD 生成数据库。我注意到该工具创建了从父表到子表的主键和外键。此后,我将该工具创建的关系包含到 XSD 中,但这些 ID 不在 XML 文件中。

我运行 SQLXML 代码,我得到一个错误,我无法插入到主键列中。如果我删除主键并使它们可以为空,则会插入数据,但我无法关联不同表中的数据。

我需要将唯一 ID 从主父表保留到子表,或者尝试让 SQLXML 忽略主键,但将它们插入子节点(相关表)。如果您查看下面的 XSD,您会注意到在关系标签中,我已经包含了 XSD2DB 工具生成的主键和外键。有没有办法让 SQLXML 填充这些或允许 MSSQL 自增?我参考这里批量加载到标识列。非常感谢任何帮助!

XSD 示例(道歉必须用 Foo 替换一个常用词):

     <?xml version="1.0" encoding="utf-8"?>
 <xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:sql="urn:schemas-microsoft-com:mapping-schema">
 <xs:annotation>
     <xs:appinfo>
       <sql:relationship name="FoosFoo"
                         parent="Foos"
                         parent-key="Foos_Id"
                         child="Foo"
                         child-key="Foos_Id" 
                         />      
       <sql:relationship name="FooFooIdentification"
                         parent="Foo"
                         parent-key="Foo_Id"
                         child="FooIdentification"
                         child-key="Foo_Id" 
                         />
       <sql:relationship name="FooIdentificationFooFlags"
                         parent="FooIdentification"
                         parent-key="FooIdentification_Id"
                         child="FooFlags"
                         child-key="FooIdentification_Id" 
                         />
       <sql:relationship name="FooFlagsFooFlag"
                         parent="FooFlags"
                         parent-key="FooFlags_Id"
                         child="FooFlag"
                         child-key="FooFlags_Id" 
                         />
       <sql:relationship name="FooFlagFooFlagDetails"
                         parent="FooFlag"
                         parent-key="FooFlag_Id"
                         child="FooFlagDetails"
                         child-key="FooFlag_Id" 
                         />      
       <sql:relationship name="FooContacts"
                         parent="Foo"
                         parent-key="Foo_Id"
                         child="Contacts"
                         child-key="Foo_Id" 
                         />                        
       <sql:relationship name="ContactsContact"
                         parent="Contacts"
                         parent-key="Contacts_Id"
                         child="Contact"
                         child-key="Contacts_Id" 
                         />                        
       <sql:relationship name="ContactContactTypes"
                         parent="Contact"
                         parent-key="Contact_Id"
                         child="ContactTypes"
                         child-key="Contact_Id" 
                         />                        
       <sql:relationship name="ContactTypesContactType"
                         parent="ContactTypes"
                         parent-key="ContactTypes_Id"
                         child="ContactType"
                         child-key="ContactTypes_Id" 
                         />                        
       <sql:relationship name="ContactTypeContactTypeCode"
                         parent="ContactType"
                         parent-key="ContactType_Id"
                         child="ContactTypeCode"
                         child-key="ContactType_Id" 
                         />
       <sql:relationship name="FooAddresses"
                         parent="Foo"
                         parent-key="Foo_Id"
                         child="Addresses"
                         child-key="Foo_Id" 
                         />                        
       <sql:relationship name="AddressesAddress"
                         parent="Addresses"
                         parent-key="Addresses_Id"
                         child="Address"
                         child-key="Addresses_Id" 
                         />                                                        
     </xs:appinfo>
   </xs:annotation>
     <xs:element name="FooBulkXMLFile" sql:is-constant="1">
         <xs:complexType>
             <xs:sequence>
                 <xs:element minOccurs="0" name="Header" sql:relation="Header">
                     <xs:complexType>
                         <xs:sequence>
                             <xs:element minOccurs="0" name="DateTimeCreated" type="xs:string" />
                             <xs:element minOccurs="0" name="FileType" type="xs:string" />
                             <xs:element minOccurs="0" name="MonthlyDate" nillable="true" />
                             <xs:element minOccurs="0" name="DailyDate" type="xs:string" />
                             <xs:element minOccurs="0" name="FooSourceSystem" type="xs:string" />
                             <xs:element minOccurs="0" name="FooSourceVersion" type="xs:string" />
                             <xs:element minOccurs="0" name="FooCount" type="xs:long" />
                         </xs:sequence>
                     </xs:complexType>
                 </xs:element>
                 <xs:element minOccurs="0" name="Foos" sql:relation="Foos">
                     <xs:complexType>
                         <xs:sequence>
                             <xs:element minOccurs="0" maxOccurs="unbounded" name="Foo" sql:relation="Foo" sql:relationship="FoosFoo">
                                 <xs:complexType>
                                     <xs:sequence>
                                         <xs:element minOccurs="0" name="FooIdentification" sql:relation="FooIdentification" sql:relationship="FooFooIdentification">
                                             <xs:complexType>
                                                 <xs:sequence>
                                                     <xs:element minOccurs="0" name="FooNumber" type="xs:string" />
                                                     <xs:element minOccurs="0" name="IsActive" type="xs:boolean" />
                                                     <xs:element minOccurs="0" name="CountryOfOriginCode" type="xs:string" />
                                                     <xs:element minOccurs="0" name="FooName" type="xs:string" />
                                                     <xs:element minOccurs="0" name="CreatedDate" type="xs:string" />
                                                     <xs:element minOccurs="0" name="EditDate" type="xs:string" />
                                                     <xs:element minOccurs="0" name="FooFlags" sql:relation="FooFlags" sql:relationship="FooIdentificationFooFlags">
                                                         <xs:complexType>
                                                             <xs:sequence>
                                                                 <xs:element minOccurs="0" maxOccurs="unbounded" name="FooFlag" sql:relation="FooFlag" sql:relationship="FooFlagsFooFlag">
                                                                     <xs:complexType>
                                                                         <xs:sequence>
                                                                             <xs:element minOccurs="0" name="FooFlagType" type="xs:string" />
                                                                             <xs:element minOccurs="0" name="FooFlagDescription" type="xs:string" />
                                                                             <xs:element minOccurs="0" name="FooFlagValue" type="xs:boolean" />
                                                                             <xs:element minOccurs="0" name="FooFlagLastVerificationDate" type="xs:string" />
                                                                             <xs:element minOccurs="0" name="FooFlagDetails" sql:relation="FooFlagDetails" sql:relationship="FooFlagFooFlagDetails">
                                                                                 <xs:complexType>
                                                                                     <xs:sequence>
                                                                                         <xs:element minOccurs="0" name="FooFlagDetail" />
                                                                                     </xs:sequence>
                                                                                 </xs:complexType>
                                                                             </xs:element>
                                                                         </xs:sequence>
                                                                     </xs:complexType>
                                                                 </xs:element>
                                                             </xs:sequence>
                                                         </xs:complexType>
                                                     </xs:element>
                                                 </xs:sequence>
                                             </xs:complexType>
                                         </xs:element>                                        
                                         <xs:element minOccurs="0" name="Contacts" sql:relation="Contacts" sql:relationship="FooContacts">
                                             <xs:complexType>
                                                 <xs:sequence>
                                                     <xs:element minOccurs="0" maxOccurs="unbounded" name="Contact" sql:relation="Contact" sql:relationship="ContactsContact">
                                                         <xs:complexType>
                                                             <xs:sequence>
                                                                 <xs:element minOccurs="0" name="ContactID" type="xs:long" />
                                                                 <xs:element minOccurs="0" name="ContactTypes" sql:relation="ContactTypes" sql:relationship="ContactContactTypes">
                                                                     <xs:complexType>
                                                                         <xs:sequence>
                                                                             <xs:element minOccurs="0" name="ContactType" sql:relation="ContactType" sql:relationship="ContactTypesContactType">
                                                                                 <xs:complexType>
                                                                                     <xs:sequence>
                                                                                         <xs:element minOccurs="0" maxOccurs="unbounded" name="ContactTypeCode" type="xs:string" sql:field="ContactTypeCode_Column"  sql:relation="ContactTypeCode" sql:relationship="ContactTypeContactTypeCode" />
                                                                                     </xs:sequence>
                                                                                 </xs:complexType>
                                                                             </xs:element>
                                                                         </xs:sequence>
                                                                     </xs:complexType>
                                                                 </xs:element>                                                        
                                                                 <xs:element minOccurs="0" name="Name" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="Surname" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="EmailAddress" type="xs:string" /><xs:element minOccurs="0" name="CreatedDate" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="EditDate" type="xs:string" />
                                                             </xs:sequence>
                                                         </xs:complexType>
                                                     </xs:element>
                                                 </xs:sequence>
                                             </xs:complexType>
                                         </xs:element>
                                         <xs:element minOccurs="0" name="Addresses"  sql:relation="Addresses" sql:relationship="FooAddresses">
                                             <xs:complexType>
                                                 <xs:sequence>
                                                     <xs:element minOccurs="0" maxOccurs="unbounded" name="Address"  sql:relation="Address" sql:relationship="AddressesAddress">
                                                         <xs:complexType>
                                                             <xs:sequence>
                                                                 <xs:element minOccurs="0" name="AddressID" type="xs:long" />
                                                                 <xs:element minOccurs="0" name="IsPreferred" type="xs:boolean" />
                                                                 <xs:element minOccurs="0" name="IsActive" type="xs:boolean" />
                                                                 <xs:element minOccurs="0" name="AddressTypeCode" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="AddressLine1" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="AddressLine2" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="CountryCode" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="ProvinceCode" nillable="true" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="DistrictCode" nillable="true" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="MunicipalityCode" nillable="true" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="CityCode" nillable="true" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="SuburbCode" nillable="true" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="WardCode" nillable="true" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="PostalCode" nillable="true" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="IsPostalAddress" type="xs:boolean" />
                                                                 <xs:element minOccurs="0" name="IsDeliveryAddress" type="xs:boolean" />
                                                                 <xs:element minOccurs="0" name="IsPhysicalAddress" type="xs:boolean" />
                                                                 <xs:element minOccurs="0" name="IsPaymentAddress" type="xs:boolean" />
                                                                 <xs:element minOccurs="0" name="Field1" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="Field2" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="Field3" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="CreatedDate" type="xs:string" />
                                                                 <xs:element minOccurs="0" name="EditDate" type="xs:string" />
                                                             </xs:sequence>
                                                         </xs:complexType>
                                                     </xs:element>
                                                 </xs:sequence>
                                             </xs:complexType>
                                         </xs:element>                                        
                                     </xs:sequence>
                                 </xs:complexType>
                             </xs:element>
                         </xs:sequence>
                     </xs:complexType>
                 </xs:element>
             </xs:sequence>
         </xs:complexType>
     </xs:element>
 </xs:schema>

C# SQLXML 代码:

public static void TestSqlXmlBulk()
    
        try
        
            SQLXMLBULKLOADLib.SQLXMLBulkLoad4Class xs;
            xs = new SQLXMLBULKLOADLib.SQLXMLBulkLoad4Class
            
                ConnectionString = @"Provider=sqloledb;server=foo\Foo01;database=FooXsd;integrated security=SSPI",
                ErrorLogFile = @"c:\tmp\error.xml",
                KeepIdentity = false,
                CheckConstraints = false,
                Transaction = false
            ;

            var list = Directory.GetFiles(@"c:\tmp\extract\", "foo*.xml");

            foreach (var f in list)
            
                Console.WriteLine("0 - Processing 1", DateTime.Now.ToString("hh:mm:ss.fff"), f);
                xs.Execute(@"c:\tmp\foo_rel.xsd", f);
            

            xs = null;
        
        catch (Exception x)
        
            throw x;
        
    

【问题讨论】:

请编辑您的问题并添加用于将 XML 加载到数据库中的脚本。 【参考方案1】:

(1)源代码正确有如下设置:

KeepIdentity = false

(2) 每个有IDENTITY 列的表在XSD 中都应该有sql:key-fields="PrimaryKeyColumn" 属性。

例如,

<xs:element minOccurs="0" name="Foos" sql:relation="Foos">

应作如下调整:

<xs:element minOccurs="0" name="Foos" sql:relation="Foos" sql:key-fields="Foos_Id">

【讨论】:

感谢您,对延迟回复表示歉意。我尝试了您的解决方案,不幸的是我收到“所有绑定列都是只读的”错误。注意:主键在数据库中是自增的,所以技术上 SQLXML 应该忽略这些并插入。我目前正在调查该错误。我还将发布我一直在研究的替代方案。 我建议从一个小的模拟 XML/XSD 开始,只为两个具有关系和 IDENTITY 列的表。让它发挥作用,然后逐个添加表格。

以上是关于SQLXML 4 - 批量插入 xml 数据的主要内容,如果未能解决你的问题,请参考以下文章

mysql存储过程怎样批量插入数据

Oracle 批量插入数据怎么做

Oracle 批量插入数据怎么做

Python批量插入问题?

oracle表批量插入数据

SQL中用循环批量插入数据如何实现