Partager via


sql:relationship et la règle de tri par clé (SQLXML 4.0)

Dans la mesure où la fonctionnalité de chargement en masse XML génère des enregistrements lorsque les nœuds de ces derniers entrent dans l'étendue, et qu'elle envoie ces enregistrements à Microsoft SQL Server lorsque les nœuds correspondants sortent de l'étendue, les données de l'enregistrement doivent être présentes dans l'étendue du nœud. 

Examinez le schéma XSD suivant, dans lequel la relation un-à-plusieurs entre les éléments <Customer> et <Order> (un client peut passer de nombreuses commandes) est spécifiée à l'aide de l'élément <sql:relationship> :

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

Lorsque le nœud de l'élément <Customer> entre dans l'étendue, la fonctionnalité de chargement en masse XML génère un enregistrement de client. Cet enregistrement est conservé jusqu'à ce que la fonctionnalité de chargement en masse XML lise </Customer>. Lors du traitement du nœud de l'élément <Order>, la fonctionnalité de chargement en masse XML utilise <sql:relationship> pour obtenir la valeur de la colonne de clé étrangère CustomerID de la table CustOrder de l'élément parent <Customer>, car l'élément <Order> ne spécifie pas l'attribut CustomerID. Cela signifie que lors de la définition de l'élément <Customer>, vous devez spécifier l'attribut CustomerID dans le schéma avant de spécifier <sql:relationship>. Sinon, lorsqu'un élément <Order> entre dans l'étendue, la fonctionnalité de chargement en masse XML génère un enregistrement pour la table CustOrder, et lorsqu'elle atteint la balise de fin </Order>, elle envoie l'enregistrement à SQL Server sans la valeur de colonne clé étrangère CustomerID.

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

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))
    GO
    
  2. Enregistrez l'exemple de données ci-après sous le nom SampleXMLData.xml :

    <ROOT>  
      <Customers>
        <CompanyName>Hanari Carnes</CompanyName>
        <City>NY</City>
        <Order OrderID="1" />
        <Order OrderID="2" />
        <CustomerID>1111</CustomerID>
      </Customers>
      <Customers>
        <CompanyName>Toms Spezialitten</CompanyName>
         <City>LA</City>  
        <Order OrderID="3" />
        <CustomerID>1112</CustomerID>
      </Customers>
      <Customers>
        <CompanyName>Victuailles en stock</CompanyName>
        <Order OrderID="4" />
        <CustomerID>1113</CustomerID>
      </Customers>
    </ROOT>
    
  3. Pour effectuer le chargement en masse XML, enregistrez l'exemple Microsoft Visual Basic Scripting Edition (VBScript) suivant sous le nom MySample.vbs, puis exécutez-le :

    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.Transaction=True
    objBL.Execute "c:\SampleSchema.xml", "c:\SampleXMLData.xml"
    set objBL=Nothing
    

    Il en résulte que la fonctionnalité de chargement en masse XML insère une valeur NULL dans la colonne de clé étrangère CustomerID de la table CustOrder. Si vous modifiez l'exemple de données XML de sorte que l'élément enfant <CustomerID> apparaisse avant l'élément enfant <Order>, vous obtenez le résultat attendu : la fonctionnalité de chargement en masse XML insère la valeur de clé étrangère spécifiée dans la colonne.

Voici le schéma XDR équivalent :

<?xml version="1.0" ?>
<Schema xmlns="urn:schemas-microsoft-com:xml-data" 
        xmlns:dt="urn:schemas-microsoft-com:xml:datatypes"  
        xmlns:sql="urn:schemas-microsoft-com:xml-sql" > 
   <ElementType name="CustomerID"  />
   <ElementType name="CompanyName" />
   <ElementType name="City"        />

   <ElementType name="root" sql:is-constant="1">
      <element type="Customers" />
   </ElementType>

   <ElementType name="Customers" sql:relation="Cust" >
      <element type="CustomerID" sql:field="CustomerID" />
      <element type="CompanyName" sql:field="CompanyName" />
      <element type="City" sql:field="City" />
      <element type="Order" >
                 <sql:relationship
                        key-relation    ="Cust"
                        key             ="CustomerID"
                        foreign-key     ="CustomerID"
                        foreign-relation="CustOrder" />
      </element>
   </ElementType>
    <ElementType name="Order" sql:relation="CustOrder" >
      <AttributeType name="OrderID" />
      <AttributeType name="CustomerID" />
      <attribute type="OrderID" />
      <attribute type="CustomerID" />
    </ElementType>
</Schema>