Proceso de generación de registros (SQLXML 4.0)

Se aplica a:SQL ServerAzure SQL Database

La carga masiva XML procesa los datos de entrada XML y prepara los registros para las tablas adecuadas de Microsoft SQL Server. La lógica de carga masiva XML determina cuándo se va a generar un nuevo registro, qué valores de elemento secundario o atributo se van a copiar en los campos del registro y cuando el registro está completo y listo para enviarse a SQL Server para su inserción.

La carga masiva XML no carga los datos de entrada XML completos en la memoria y no genera conjuntos de registros completos antes de enviar datos a SQL Server. Esto ocurre porque los datos de entrada XML pueden ser un documento de gran tamaño y cargar todo el documento en la memoria puede resultar costoso. En lugar de ello, la carga masiva XML hace lo siguiente:

  1. Analiza el esquema de asignación y prepara el plan de ejecución necesario.

  2. Aplica el plan de ejecución a los datos del flujo de entrada.

Este procesamiento secuencial hace que sea importante proporcionar los datos de entrada XML de un modo específico. Debe entender la forma en que la carga masiva XML analiza el esquema de asignación y la forma en que se produce el proceso de generación de registros. Sabiendo esto, podrá proporcionar un esquema de asignación para la carga masiva XML que genere los resultados que desee.

La carga masiva XML administra anotaciones comunes del esquema de asignación, incluidas las asignaciones de columna y tabla (que se especifican de forma explícita mediante anotaciones o de forma implícita a través de la asignación predeterminada), así como relaciones de unión.

Nota:

Se supone que está familiarizado con los esquemas de asignación XSD o XDR anotados. Para obtener más información sobre los esquemas, vea Introducción a esquemas XSD anotados (SQLXML 4.0) o Esquemas XDR anotados (en desuso en SQLXML 4.0).

Para entender el proceso de generación de registros es necesario comprender los conceptos siguientes:

  • Ámbito de un nodo

  • Regla de generación de registros

  • Subconjunto de registros y la regla de orden de clave

  • Excepciones a la regla de generación de registros

Ámbito de un nodo

Un nodo (un elemento o un atributo) de un documento XML entra en el ámbito cuando la carga masiva XML la encuentra en el flujo de datos de entrada XML. En el caso de un nodo de elemento, la etiqueta inicial del elemento introduce el elemento en el ámbito. En el caso de un nodo de atributo, el nombre de atributo introduce el atributo en el ámbito.

Un nodo sale del ámbito cuando no hay más datos de él, ya sea en la etiqueta final (en el caso de un nodo de elemento) o al final de un valor de atributo (en el caso de un nodo de atributo).

Regla de generación de registros

Cuando un nodo (elemento o atributo) entra en el ámbito, significa que existe el potencial de generar un registro a partir de ese nodo. El período de vida del registro termina cuando el nodo asociado sale del ámbito. Cuando el nodo sale del ámbito, la carga masiva XML considera el registro generado completo (con datos) y lo envía a SQL Server para su inserción.

Por ejemplo, fíjese en el siguiente fragmento de esquema XSD:

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

El esquema especifica un <elemento Customer con atributos CustomerID> y CompanyName. La anotación sql:relation asigna el <elemento Customer> a la tabla Customers.

Fíjese en este fragmento de un documento XML:

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

Cuando la carga masiva XML se proporciona con el esquema descrito en los párrafos anteriores y con datos XML como entrada, procesa los nodos (elementos y atributos) en los datos de origen, tal y como se indica a continuación:

  • La etiqueta de inicio del primer <elemento Customer> trae ese elemento en el ámbito. Este nodo se asigna a la tabla Customers. Por lo tanto, la carga masiva XML genera un registro para la tabla Customers.

  • En el esquema, todos los atributos del <elemento Customer> se asignan a columnas de la tabla Customers. A medida que estos atributos entran en el ámbito, la carga masiva XML copia sus valores en el registro del cliente ya generado por el ámbito primario.

  • Cuando la carga masiva XML alcanza la etiqueta final del <elemento Customer> , el elemento sale del ámbito. Esto hace que la carga masiva XML tenga en cuenta el registro completado y enviarlo a SQL Server.

La carga masiva XML sigue este proceso para cada elemento Customer> posterior<.

Importante

En este modelo, dado que se inserta un registro cuando se alcanza la etiqueta final (o cuando el nodo sale del ámbito), deberá definir todos los datos asociados al registro dentro del ámbito del nodo.

Subconjunto de registros y la regla de ordenación de claves

Cuando se especifica un esquema de asignación que usa <sql:relationship>, el término subconjunto hace referencia al conjunto de registros que se generan en el lado externo de la relación. En el ejemplo siguiente, los registros CustOrder se encuentran en el lado externo, <sql:relationship>.

Por ejemplo, supongamos que una base de datos contiene las tablas siguientes:

  • Cust (CustomerID, CompanyName, City)

  • CustOrder (CustomerID, OrderID)

La columna CustomerID de la tabla CustOrder es una clave externa que hace referencia a la clave principal CustomerID de la tabla Cust.

Ahora, fíjese en la vista XML tal y como se especifica en el siguiente esquema XSD anotado. Este esquema usa <sql:relationship> para especificar la relación entre las tablas Cust y 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>  

Los datos XML de ejemplo y los pasos para crear un ejemplo funcional se proporcionan a continuación.

  • Cuando un <nodo de elemento Customer> del archivo de datos XML entra en el ámbito, la carga masiva XML genera un registro para la tabla Cust. La carga masiva XML copia los valores de columna necesarios (CustomerID, CompanyName y City) de los <elementos secundarios CustomerID>, <CompanyName> y <City> a medida que estos elementos entran en el ámbito.

  • Cuando un <nodo de elemento Order> entra en el ámbito, la carga masiva XML genera un registro para la tabla CustOrder. La carga masiva XML copia el valor del atributo OrderID en este registro. El valor necesario para la columna CustomerID se obtiene del elemento secundario CustomerID del< elemento Customer>.>< La carga masiva XML usa la información especificada en <sql:relationship> para obtener el valor de clave externa CustomerID para este registro, a menos que se especifique el atributo CustomerID en el <elemento Order> . La regla general es que si el elemento secundario especifica explícitamente un valor para el atributo de clave externa, la carga masiva XML usa ese valor y no obtiene el valor del elemento primario mediante el valor sql:relationship> especificado<. Dado que este <nodo de elemento Order> sale del ámbito, la carga masiva XML envía el registro a SQL Server y, a continuación, procesa todos los nodos del elemento Order> subsiguientes< de la misma manera.

  • Por último, el <nodo elemento Customer> sale del ámbito. En ese momento, la carga masiva XML envía el registro de cliente a SQL Server. La carga masiva XML sigue este proceso para todos los clientes subsiguientes del flujo de datos XML.

A continuación se indican dos observaciones sobre el esquema de asignación:

  • Cuando el esquema cumple la regla de "contención" (por ejemplo, todos los datos asociados al cliente y el pedido se definen dentro del ámbito de los nodos de elemento Customer> y Order asociados<), la carga masiva se realiza correctamente.><

  • Al describir el <elemento Customer> , sus elementos secundarios se especifican en el orden adecuado. En este caso, se especifica el <elemento secundario CustomerID> antes del <elemento secundario Order> . Esto significa que, en el archivo de datos XML de entrada, el <valor del elemento CustomerID> está disponible como valor de clave externa cuando el <elemento Order> entra en el ámbito. Primero se especifican los atributos de clave; ésta es la "regla de orden de clave".

    Si especifica el <elemento secundario CustomerID> después del <elemento secundario Order> , el valor no está disponible cuando el <elemento Order> entra en el ámbito. Cuando se lee la <etiqueta final /Order> , el registro de la tabla CustOrder se considera completo y se inserta en la tabla CustOrder con un valor NULL para la columna CustomerID, que no es el resultado deseado.

Para crear un ejemplo funcional

  1. Guarde el esquema que se proporciona en este ejemplo como SampleSchema.xml.

  2. Cree estas tablas:

    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. Guarde los siguientes datos de entrada XML de ejemplo como 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. Para ejecutar la carga masiva XML, guarde y ejecute el siguiente ejemplo de Microsoft Visual Basic Scripting Edition (VBScript) (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  
    

Excepciones a la regla de generación de registros

La carga masiva XML no genera ningún registro para un nodo cuando entra en el ámbito si ese nodo es de tipo IDREF o IDREFS. Debe asegurarse de que se realice una descripción completa del registro en algún lugar del esquema. Las anotaciones dt:type="nmtokens" se omiten igual que el tipo IDREFS.

Por ejemplo, considere el siguiente esquema XSD que describe <los elementos Customer> y <Order> . El <elemento Customer> incluye un atributo OrderList del tipo IDREFS. La <etiqueta sql:relationship> especifica la relación uno a varios entre el cliente y la lista de pedidos.

Éste es el esquema:

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

Dado que La carga masiva omite los nodos del tipo IDREFS, no hay ninguna generación de registros cuando el nodo de atributo OrderList entra en el ámbito. Por lo tanto, si desea que los registros de pedidos se agreguen a la tabla Orders, debe describir estos pedidos en alguna parte del esquema. En este esquema, especificar el <elemento Order> garantiza que la carga masiva XML agrega los registros de pedido a la tabla Orders. El <elemento Order> describe todos los atributos necesarios para rellenar el registro de la tabla CustOrder.

Debe asegurarse de que los valores CustomerID y OrderID del <elemento Customer> coincidan con los valores del <elemento Order> . Mantener la integridad referencial es responsabilidad suya.

Para probar un ejemplo funcional

  1. Cree estas tablas:

    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. Guarde el esquema de asignación que se proporciona en este ejemplo como SampleSchema.xml.

  3. Guarde los siguientes datos XML de ejemplo como 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. Para ejecutar la carga masiva XML, guarde y ejecute este ejemplo de 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