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 数据的主要内容,如果未能解决你的问题,请参考以下文章