Delen via


Record Generatieproces (SQLXML 4.0)

Van toepassing op:SQL ServerAzure SQL Database

XML Bulk Load verwerkt de XML-invoergegevens en bereidt records voor voor de juiste tabellen in Microsoft SQL Server. De logica in XML Bulk Load bepaalt wanneer een nieuw record wordt gegenereerd, welke kind-element- of attribuutwaarden in de velden van het record worden gekopieerd, en wanneer het record compleet is en klaar om naar SQL Server te worden gestuurd voor invoeging.

XML Bulk Load laadt niet de volledige XML-invoergegevens in het geheugen en produceert geen volledige recordsets voordat de data naar SQL Server wordt gestuurd. Dit komt doordat XML-invoerdata een groot document kan zijn en het laden van het hele document in het geheugen duur kan zijn. In plaats daarvan doet XML Bulk Load het volgende:

  1. Analyseert het mappingschema en stelt het benodigde uitvoeringsplan op.

  2. Past het uitvoeringsplan toe op de data in de invoerstroom.

Deze sequentiële verwerking maakt het belangrijk om de XML-invoergegevens op een specifieke manier te leveren. Je moet begrijpen hoe XML Bulk Load het mappingschema analyseert en hoe het recordgeneratieproces verloopt. Met dit inzicht kun je een mappingschema leveren naar XML Bulk Load dat de gewenste resultaten oplevert.

XML Bulk Load verwerkt veelvoorkomende mapping-schema-annotaties, waaronder kolom- en tabelmappings (expliciet gespecificeerd door annotaties of impliciet via de standaardmapping), en join-relaties.

Opmerking

Er wordt aangenomen dat je bekend bent met geannoteerde XSD- of XDR-mappingschema's. Voor meer informatie over schema's, zie Introduction to Annotated XSD Schemas (SQLXML 4.0) of Annotated XDR Schemas (Verouderd in SQLXML 4.0).

Begrip van recordgeneratie vereist het begrijpen van de volgende concepten:

  • Reikwijdte van een knoop

  • Regel voor recordgeneratie

  • Recordsubset en de Key Ordering Rule

  • Uitzonderingen op de regel voor recordgeneratie

Reikwijdte van een knoop

Een knoop (een element of een attribuut) in een XML-document komt in de scope wanneer XML Bulk Load het tegenkomt in de XML-invoerdatastroom. Voor een elementknoop brengt de starttag van het element het element in scope. Voor een attribuutknoop brengt de attribuutnaam het attribuut in scope.

Een node verlaat de scope wanneer er geen data meer voor is: hetzij bij de eindtag (in het geval van een elementknoop) of aan het einde van een attribuutwaarde (in het geval van een attribuutknoop).

Regel voor recordgeneratie

Wanneer een node (element of attribuut) in scope komt, is er een mogelijkheid om een record uit die node te genereren. Het record leeft zolang de bijbehorende node binnen scope valt. Wanneer de node buiten scope valt, beschouwt XML Bulk Load het gegenereerde record als compleet (met data) en stuurt het naar SQL Server voor invoeging.

Beschouw bijvoorbeeld het volgende XSD-schemafragment:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
            xmlns:sql="urn:schemas-microsoft-com:mapping-schema">  
  <xsd:element name="Customer" sql:relation="Customers" >  
   <xsd:complexType>  
     <xsd:attribute name="CustomerID" type="xsd:string" />  
     <xsd:attribute name="CompanyName" type="xsd:string" />  
    </xsd:complexType>  
  </xsd:element>  
</xsd:schema>  

Het schema specificeert een <Customer-element> met attributen CustomerID en CompanyName . De sql:relation-annotatie koppelt het <Customer-element> aan de Customers-tabel.

Beschouw dit fragment van een XML-document:

<Customer CustomerID="1" CompanyName="xyz" />  
<Customer CustomerID="2" CompanyName="abc" />  
...  

Wanneer XML Bulk Load het schema krijgt dat in de voorgaande paragrafen is beschreven en XML-gegevens als invoer, verwerkt het de knooppunten (elementen en attributen) in de brongegevens als volgt:

  • De start-tag van het eerste <Klant-element> brengt dat element in de scope. Deze knoop wordt gekoppeld aan de Klanten-tabel. Daarom genereert XML Bulk Load een record voor de Customers-tabel.

  • In het schema worden alle attributen van het <Klant-element> gekoppeld aan kolommen van de Klanten-tabel. Naarmate deze attributen in scope komen, kopieert XML Bulk Load hun waarden naar het klantrecord dat al door de ouderscope is gegenereerd.

  • Wanneer XML Bulk Load de eindtag van het <klantelement> bereikt, valt het element buiten de scope. Dit zorgt ervoor dat XML Bulk Load het record als voltooid beschouwt en naar SQL Server stuurt.

XML Bulk Load volgt dit proces voor elk volgend <klantelement> .

Belangrijk

In dit model moet je, omdat een record wordt ingevoegd wanneer de eindtag wordt bereikt (of de node buiten scope valt), alle data die aan het record is gekoppeld binnen de scope van de node definiëren.

Recordsubset en de sleutelordeningsregel

Wanneer je een mappingschema specificeert dat sql:relationship> gebruikt<, verwijst de subsetterm naar de set records die aan de vreemde kant van de relatie worden gegenereerd. In het volgende voorbeeld bevinden de CustOrder-records zich aan de buitenlandse kant, <sql:relationship>.

Stel bijvoorbeeld dat een database de volgende tabellen bevat:

  • Cust (KlantID, Bedrijfsnaam, Stad)

  • CustOrder (CustomerID, OrderID)

De CustomerID in de CustOrder-tabel is een vreemde sleutel die verwijst naar de primaire CustomerID-sleutel in de Cust-tabel.

Overweeg nu de XML-weergave zoals gespecificeerd in het volgende geannoteerde XSD-schema. Dit schema gebruikt <sql:relationship> om de relatie tussen de Cust en CustOrder-tabellen te specificeren.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
            xmlns:sql="urn:schemas-microsoft-com:mapping-schema">  
<xsd:annotation>  
  <xsd:appinfo>  
    <sql:relationship name="CustCustOrder"  
          parent="Cust"  
          parent-key="CustomerID"  
          child="CustOrder"  
          child-key="CustomerID" />  
  </xsd:appinfo>  
</xsd:annotation>  
  
  <xsd:element name="Customers" sql:relation="Cust" >  
   <xsd:complexType>  
     <xsd:sequence>  
       <xsd:element name="CustomerID"  type="xsd:integer" />  
       <xsd:element name="CompanyName" type="xsd:string" />  
       <xsd:element name="City"        type="xsd:string" />  
       <xsd:element name="Order"   
                          sql:relation="CustOrder"  
                          sql:relationship="CustCustOrder" >  
         <xsd:complexType>  
          <xsd:attribute name="OrderID" type="xsd:integer" />  
         </xsd:complexType>  
       </xsd:element>  
     </xsd:sequence>  
    </xsd:complexType>  
  </xsd:element>  
</xsd:schema>  

De voorbeeld-XML-gegevens en de stappen om een werkend voorbeeld te maken worden hieronder gegeven.

  • Wanneer een <Customer-elementknoop> in het XML-databestand in scope komt, genereert XML Bulk Load een record voor de Cust-tabel. XML Bulk Load kopieert vervolgens de benodigde kolomwaarden (CustomerID, CompanyName en City) van de <CustomerID,><CompanyName en de City-kindelementen>>zodra deze elementen in scope komen.<

  • Wanneer een <Order-elementknoop> in scope komt, genereert XML Bulk Load een record voor de CustOrder-tabel. XML Bulk Load kopieert de waarde van het OrderID-attribuut naar dit record. De vereiste waarde voor de CustomerID-kolom wordt verkregen uit het <CustomerID-kindelement van het Customer-element>>.< XML Bulk Load gebruikt de informatie die in <sql:relationship> is gespecificeerd om de CustomerID vreemde sleutelwaarde voor dit record te verkrijgen, tenzij het CustomerID-attribuut is opgegeven in het <Order-element> . De algemene regel is dat als het kindelement expliciet een waarde specificeert voor het vreemde sleutel-attribuut, XML Bulk Load die waarde gebruikt en de waarde niet van het ouderelement verkrijgt door gebruik te maken van de gespecificeerde <sql:relationship>. Wanneer deze <Order-elementknoop> buiten scope valt, stuurt XML Bulk Load het record naar SQL Server en verwerkt vervolgens alle daaropvolgende <Order-elementknooppunten> op dezelfde manier.

  • Ten slotte gaat de <Klant-element> node buiten de scope. Op dat moment stuurt XML Bulk Load het klantrecord naar SQL Server. XML Bulk Load volgt dit proces voor alle volgende klanten in de XML-datastroom.

Hier zijn twee observaties over het mapping schema:

  • Wanneer het schema voldoet aan de "containment"-regel (bijvoorbeeld alle gegevens die aan de klant zijn gekoppeld en de bestelling is gedefinieerd binnen de scope van de bijbehorende <Klant-> en <Order-elementknooppunten> ), slaagt de bulkbelasting.

  • Bij het beschrijven van het <Customer-element> worden de kindelementen in de juiste volgorde gespecificeerd. In dit geval wordt het <CustomerID-kindelement vóór het Order-kindelement>>gespecificeerd.< Dit betekent dat in het invoer-XML-databestand de <CustomerID-elementwaarde> beschikbaar is als de vreemde sleutelwaarde wanneer het <Order-element> in scope komt. De sleutelattributen worden eerst gespecificeerd; dit is de "Key Ordering Rule."

    Als je het <CustomerID-kindelement> specificeert na het <Order-kindelement> , is de waarde niet beschikbaar wanneer het <Order-element> in scope komt. Wanneer de </Order-eindtag> vervolgens wordt gelezen, wordt het record voor de CustOrder-tabel als compleet beschouwd en wordt het in de CustOrder-tabel ingevoegd met een NULL-waarde voor de CustomerID-kolom, wat niet het gewenste resultaat is.

Om een werkmonster te maken

  1. Sla het schema dat in dit voorbeeld wordt gegeven op als SampleSchema.xml.

  2. Maak deze tabellen:

    CREATE TABLE Cust (  
                  CustomerID     int         PRIMARY KEY,  
                  CompanyName    varchar(20) NOT NULL,  
                  City           varchar(20) DEFAULT 'Seattle')  
    GO  
    CREATE TABLE CustOrder (  
                 OrderID        int         PRIMARY KEY,  
                 CustomerID     int         FOREIGN KEY REFERENCES                                          Cust(CustomerID))  
    GO  
    
  3. Sla de volgende voorbeeldinvoergegevens van XML op als SampleXMLData.xml:

    <ROOT>  
      <Customers>  
        <CustomerID>1111</CustomerID>  
        <CompanyName>Hanari Carnes</CompanyName>  
        <City>NY</City>   
        <Order OrderID="1" />  
        <Order OrderID="2" />  
      </Customers>  
    
      <Customers>  
        <CustomerID>1112</CustomerID>  
        <CompanyName>Toms Spezialitten</CompanyName>  
        <City>LA</City>  
        <Order OrderID="3" />  
      </Customers>  
      <Customers>  
        <CustomerID>1113</CustomerID>  
        <CompanyName>Victuailles en stock</CompanyName>  
        <Order OrderID="4" />  
    </Customers>  
    </ROOT>  
    
  4. Om XML Bulk Load uit te voeren, sla en voer je het volgende voorbeeld van Microsoft Visual Basic Scripting Edition (VBScript) uit (BulkLoad.vbs):

    set objBL = CreateObject("SQLXMLBulkLoad.SQLXMLBulkload.4.0")  
    objBL.ConnectionString = "provider=SQLOLEDB;data source=localhost;database=tempdb;integrated security=SSPI"  
    objBL.ErrorLogFile = "c:\error.log"  
    objBL.CheckConstraints = True  
    objBL.Execute "c:\SampleSchema.xml", "c:\SampleXMLData.xml"  
    set objBL=Nothing  
    

Uitzonderingen op de regel voor recordgeneratie

XML Bulk Load genereert geen record voor een knoop wanneer deze in scope komt als die knoop een IDREF- of IDREFS-type is. Je moet ervoor zorgen dat een volledige beschrijving van het record ergens in het schema voorkomt. De annotaties dt:type="nmtokens" worden genegeerd, net zoals het type IDREFS wordt genegeerd.

Overweeg bijvoorbeeld het volgende XSD-schema dat klant-> en orderelementen beschrijft<.>< Het <Customer-element> bevat een OrderList-attribuut van het type IDREFS. De <sql:relationship-tag> specificeert de één-op-veel-relatie tussen de klant en de lijst van bestellingen.

Dit is het schema:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
            xmlns:sql="urn:schemas-microsoft-com:mapping-schema">  
<xsd:annotation>  
  <xsd:appinfo>  
    <sql:relationship name="CustCustOrder"  
                 parent="Cust"  
                 parent-key="CustomerID"  
                 child="CustOrder"  
                 child-key="CustomerID" />  
  </xsd:appinfo>  
</xsd:annotation>  
  
  <xsd:element name="Customers" sql:relation="Cust" >  
   <xsd:complexType>  
    <xsd:attribute name="CustomerID" type="xsd:integer" />  
    <xsd:attribute name="CompanyName" type="xsd:string" />  
    <xsd:attribute name="City" type="xsd:string" />  
    <xsd:attribute name="OrderList"   
                       type="xsd:IDREFS"   
                       sql:relation="CustOrder"   
                       sql:field="OrderID"  
                       sql:relationship="CustCustOrder" >  
    </xsd:attribute>  
  </xsd:complexType>  
 </xsd:element>  
  
  <xsd:element name="Order" sql:relation="CustOrder" >  
   <xsd:complexType>  
    <xsd:attribute name="OrderID" type="xsd:string" />  
    <xsd:attribute name="CustomerID" type="xsd:integer" />  
    <xsd:attribute name="OrderDate" type="xsd:date" />  
  </xsd:complexType>  
 </xsd:element>  
</xsd:schema>  

Omdat Bulk Load de nodes van IDREFS-type negeert, vindt er geen recordgeneratie plaats wanneer het OrderList-attribuutknooppunt in scope komt. Daarom moet je, als je de orderrecords aan de Orders-tabel wilt toevoegen, die orders ergens in het schema beschrijven. In dit schema zorgt het specificeren van het <Order-element> ervoor dat XML Bulk Load de orderrecords toevoegt aan de Orders-tabel. Het <Order-element> beschrijft alle attributen die nodig zijn om het record voor de CustOrder-tabel te vullen.

Je moet ervoor zorgen dat de CustomerID- en OrderID-waarden in het <Customer-element> overeenkomen met die in het <Order-element> . U bent verantwoordelijk voor het behouden van referentieintegriteit.

Om een werkmonster te testen

  1. Maak deze tabellen:

    CREATE TABLE Cust (  
                  CustomerID     int          PRIMARY KEY,  
                  CompanyName    varchar(20)  NOT NULL,  
                  City           varchar(20)  DEFAULT 'Seattle')  
    GO  
    CREATE TABLE CustOrder (  
                  OrderID        varchar(10) PRIMARY KEY,  
                  CustomerID     int         FOREIGN KEY REFERENCES                                          Cust(CustomerID),  
                  OrderDate      datetime DEFAULT '2000-01-01')  
    GO  
    
  2. Sla het mappingschema dat in dit voorbeeld wordt gegeven op als SampleSchema.xml.

  3. Sla de volgende voorbeeld-XML-gegevens op als SampleXMLData.xml:

    <ROOT>  
      <Customers CustomerID="1111" CompanyName="Sean Chai" City="NY"  
                 OrderList="Ord1 Ord2" />  
      <Customers CustomerID="1112" CompanyName="Dont Know" City="LA"  
                 OrderList="Ord3 Ord4" />  
      <Order OrderID="Ord1" CustomerID="1111" OrderDate="1999-01-01" />  
      <Order OrderID="Ord2" CustomerID="1111" OrderDate="1999-02-01" />  
      <Order OrderID="Ord3" CustomerID="1112" OrderDate="1999-03-01" />  
      <Order OrderID="Ord4" CustomerID="1112" OrderDate="1999-04-01" />  
    </ROOT>  
    
  4. Om XML Bulk Load uit te voeren, sla en voer je dit VBScript-voorbeeld uit (SampleVB.vbs):

    set objBL = CreateObject("SQLXMLBulkLoad.SQLXMLBulkload.4.0")  
    objBL.ConnectionString = "provider=SQLOLEDB;data source=localhost;database=tempdb;integrated security=SSPI"  
    objBL.ErrorLogFile = "c:\error.log"  
    objBL.CheckConstraints=True  
    objBL.Execute "c:\SampleSchema.xml", "c:\SampleXMLData.xml"  
    set objBL=Nothing