Partage via


Processus de génération d'enregistrements (SQLXML 4.0)

S’applique à : SQL ServerAzure SQL Database

Xml Bulk Load traite les données d’entrée XML et prépare les enregistrements pour les tables appropriées dans Microsoft SQL Server. La logique dans le chargement en masse XML détermine quand générer un nouvel enregistrement, les valeurs d’élément enfant ou d’attribut à copier dans les champs de l’enregistrement, et quand l’enregistrement est terminé et prêt à être envoyé à SQL Server pour l’insertion.

Le chargement en bloc XML ne charge pas les données d’entrée XML entières en mémoire et ne produit pas de jeux d’enregistrements complets avant d’envoyer des données à SQL Server. Cela tient au fait que les données d'entrée XML peuvent correspondre à un document volumineux et que le chargement du document entier en mémoire peut s'avérer onéreux. À la place, le chargement en masse XML effectue les opérations suivantes :

  1. Il analyse le schéma de mappage et prépare le plan d'exécution nécessaire.

  2. Il applique le plan d'exécution aux données dans le flux d'entrée.

Ce traitement séquentiel fait qu'il est important de fournir les données d'entrée XML d'une manière spécifique. Vous devez comprendre comment le chargement en masse XML analyse le schéma de mappage et comment le processus de génération d'enregistrements se produit. Comprendre cela vous permet de fournir un schéma de mappage au chargement en masse XML qui produit les résultats que vous souhaitez.

Le chargement en masse XML gère les annotations de schéma de mappage courantes, y compris les mappages de colonne et de table (spécifiés explicitement à l'aide d'annotations ou implicitement par le biais du mappage par défaut), ainsi que les relations de jointure.

Remarque

Cette rubrique suppose que vous connaissez bien les schémas de mappage XDR ou XSD annotés. Pour plus d’informations sur les schémas, consultez Présentation des schémas XSD annotés (SQLXML 4.0) ou Des schémas XDR annotés (déconseillés dans SQLXML 4.0).

Pour comprendre la génération d'enregistrements, vous devez comprendre les concepts suivants :

  • Étendue d'un nœud

  • Règle de génération d'enregistrements

  • Sous-ensemble d'enregistrements et règle de tri par clé

  • Exceptions à la règle de génération d'enregistrements

Étendue d’un nœud

Un nœud (un élément ou un attribut) dans un document XML entre dans l’étendue lorsque le chargement en masse XML le rencontre dans le flux de données d’entrée XML. Pour un nœud d'élément, la balise de début de l'élément place l'élément dans l'étendue. Pour un nœud d'attribut, le nom d'attribut place l'attribut dans l'étendue.

Un nœud quitte l'étendue lorsqu'il ne reste plus de données pour lui : soit au niveau de la balise de fin (dans le cas d'un nœud d'élément), soit à la fin d'une valeur d'attribut (dans le cas d'un nœud d'attribut).

Règle de génération d'enregistrements

Lorsqu'un nœud (élément ou attribut) entre dans l'étendue, il est possible de générer un enregistrement à partir de ce nœud. L'enregistrement dure tant que le nœud associé est dans l'étendue. Lorsque le nœud sort de l’étendue, le chargement en masse XML prend en compte l’enregistrement généré terminé (avec des données) et l’envoie à SQL Server pour l’insertion.

Considérons, par exemple, le fragment de schéma XSD suivant :

<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>  

Le schéma spécifie un <élément Customer> avec des attributs CustomerID et CompanyName . L’annotation sql :relation mappe l’élément <Customer> à la table Customers.

Considérez ce fragment d'un document XML :

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

Lorsque le chargement en masse XML est fourni avec le schéma décrit dans les paragraphes précédents et les données XML comme entrée, il traite les nœuds (éléments et attributs) dans les données sources comme suit :

  • La balise de début du premier <élément Customer> apporte cet élément dans l’étendue. Ce nœud est mappé à la table Customers. Par conséquent, le chargement en masse XML génère un enregistrement pour la table Customers.

  • Dans le schéma, tous les attributs de l’élément <Customer> sont mappés aux colonnes de la table Customers. Lorsque ces attributs entrent dans l'étendue, le chargement en masse XML copie leurs valeurs dans l'enregistrement de client qui est déjà généré par l'étendue parente.

  • Lorsque le chargement en bloc XML atteint la balise de fin de l’élément <Customer> , l’élément sort de l’étendue. Cela entraîne le chargement en masse XML pour prendre en compte l’enregistrement complet et l’envoyer à SQL Server.

Le chargement en bloc XML suit ce processus pour chaque élément Customer> suivant<.

Important

Dans ce modèle, comme un enregistrement est inséré lorsque la balise de fin est atteinte (ou lorsque le nœud est hors de portée), vous devez définir toutes les données associées à l'enregistrement dans l'étendue du nœud.

Enregistrer un sous-ensemble et la règle d’ordre de clé

Lorsque vous spécifiez un schéma de mappage qui utilise <sql :relationship>, le terme de sous-ensemble fait référence à l’ensemble d’enregistrements générés du côté étranger de la relation. Dans l’exemple suivant, les enregistrements CustOrder se trouvent du côté étranger, <sql :relationship>.

Prenons l'exemple d'une base de données contenant les tables suivantes :

  • Cust (CustomerID, CompanyName, City)

  • CustOrder (CustomerID, OrderID)

CustomerID dans la table CustOrder est une clé étrangère qui fait référence à la clé primaire CustomerID dans la table Cust.

À présent, considérez la vue XML telle qu'elle est spécifiée dans le schéma XSD annoté ci-dessous. Ce schéma utilise <sql :relationship> pour spécifier la relation entre les tables Cust et CustOrder.

<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>  

L'exemple de données XML et les étapes de création d'un exemple fonctionnel sont fournis ci-dessous.

  • Lorsqu’un nœud d’élément <Customer> dans le fichier de données XML entre dans l’étendue, le chargement en masse XML génère un enregistrement pour la table Cust. Le chargement en bloc XML copie ensuite les valeurs de colonne nécessaires (CustomerID, CompanyName et City) à partir des <éléments CustomerID>,< CompanyName> et <City>, car ces éléments entrent dans l’étendue.

  • Lorsqu’un nœud d’élément <Order> entre dans l’étendue, le chargement en masse XML génère un enregistrement pour la table CustOrder. Xml Bulk Load copie la valeur de l’attribut OrderID dans cet enregistrement. La valeur requise pour la colonne CustomerID est obtenue à partir de l’élément <enfant CustomerID> de l’élément <Customer>. Le chargement en bloc XML utilise les informations spécifiées dans sql :relationship> pour obtenir la valeur de clé étrangère CustomerID pour cet enregistrement, sauf si l’attribut CustomerID a été spécifié dans l’élément< Order>.< La règle générale est que si l’élément enfant spécifie explicitement une valeur pour l’attribut de clé étrangère, le chargement en bloc XML utilise cette valeur et n’obtient pas la valeur de l’élément parent à l’aide de la relation sql :relationship> spécifiée<. À mesure que ce nœud d’élément Order> sort de l’étendue, le chargement en masse XML envoie l’enregistrement à SQL Server, puis traite tous les nœuds d’élément Order> suivants <de la même manière.<

  • Enfin, le nœud de l’élément <Customer> sort de l’étendue. À ce stade, le chargement en masse XML envoie l’enregistrement client à SQL Server. Le chargement en masse XML suit ce processus pour tous les clients suivants dans le flux de données XML.

Voici deux observations à propos du schéma de mappage :

  • Lorsque le schéma satisfait à la règle de « confinement » (par exemple, toutes les données associées au client et la commande sont définies dans l’étendue des nœuds d’élément Client> et <Commande> associés<), la charge en bloc réussit.

  • Dans la description de l’élément <Customer> , ses éléments enfants sont spécifiés dans l’ordre approprié. Dans ce cas, l’élément enfant CustomerID> est spécifié avant l’élément <Enfant Order>.< Cela signifie que dans le fichier de données XML d’entrée, la valeur de l’élément <CustomerID> est disponible en tant que valeur de clé étrangère lorsque l’élément <Order> entre dans l’étendue. Les attributs de clé sont spécifiés en premier ; ceci est la « règle de tri par clé ».

    Si vous spécifiez l’élément enfant CustomerID> après l’élément< Enfant Order>, la valeur n’est pas disponible lorsque l’élément <Order> entre dans l’étendue.< Lorsque la <balise de fin /Order> est ensuite lue, l’enregistrement de la table CustOrder est considéré comme terminé et est inséré dans la table CustOrder avec une valeur NULL pour la colonne CustomerID, ce qui n’est pas le résultat souhaité.

Pour créer un exemple fonctionnel

  1. Enregistrez le schéma fourni dans cet exemple sous le nom SampleSchema.xml.

  2. Créez les tables suivantes :

    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. Enregistrez l'exemple de données d'entrée XML ci-après sous le nom 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. Pour exécuter le chargement en bloc XML, enregistrez et exécutez l’exemple Microsoft Visual Basic Scripting Edition (VBScript) suivant (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  
    

Exceptions à la règle de génération d'enregistrements

Le chargement en masse XML ne génère pas d'enregistrement pour un nœud lorsqu'il entre dans l'étendue si ce nœud est de type IDREF ou IDREFS. Vous devez vous assurer qu'une description complète de l'enregistrement se produit à un point quelconque dans le schéma. Les annotations dt :type="nmtokens » sont ignorées tout comme le type IDREFS est ignoré.

Par exemple, considérez le schéma XSD suivant qui décrit les éléments Customer> et <Order>.< L’élément <Customer> inclut un attribut OrderList du type IDREFS. La <balise sql :relationship> spécifie la relation un-à-plusieurs entre le client et la liste des commandes.

Voici le schéma :

<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>  

Étant donné que le chargement en bloc ignore les nœuds du type IDREFS, il n’existe aucune génération d’enregistrement lorsque le nœud d’attribut OrderList entre dans l’étendue. Par conséquent, si vous souhaitez que les enregistrements de commandes soient ajoutés à la table Orders, vous devez décrire ces commandes quelque part dans le schéma. Dans ce schéma, la spécification de l’élément <Order> garantit que le chargement en bloc XML ajoute les enregistrements de commande à la table Orders. L’élément <Order> décrit tous les attributs requis pour remplir l’enregistrement de la table CustOrder.

Vous devez vous assurer que les valeurs CustomerID et OrderID dans l’élément <Customer> correspondent aux valeurs de l’élément <Order.> Vous êtes chargé de maintenir l'intégrité référentielle.

Pour tester un exemple fonctionnel

  1. Créez les tables suivantes :

    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. Enregistrez le schéma de mappage fourni dans cet exemple sous le nom SampleSchema.xml.

  3. Enregistrez l'exemple de données XML ci-après sous le nom 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. Pour exécuter le chargement en masse XML, enregistrez et exécutez cet exemple VBScript (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