Proceso de generación de registros (SQLXML 4.0)

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 la carga masiva XML determina cuándo generar un nuevo registro, qué elemento secundario o valores de atributo copiar en los campos del registro y cuándo está completo y preparado el registro 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 los 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 de la secuencia 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 acerca de los esquemas, vea Introducción a los esquemas XSD anotados (SQLXML 4.0) o Esquemas XDR anotados (obsoletos 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 lo detecta en la secuencia 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 que el registro generado está completo (de datos) y lo envía a SQL Server para insertarlo.

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 los 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 inicial del primer elemento <Customer> introduce 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 considere el registro completo y lo envíe a SQL Server.

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

Nota importanteImportante

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 orden de clave

Cuando se especifica un esquema de asignación que usa <sql:relationship>, el término subconjunto hace referencia al conjunto de registros generado en el lado externo de la relación. En el ejemplo siguiente, los registros de CustOrder están 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. A continuación, 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 secundarios 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 la clave externa CustomerID para este registro, a menos que se haya especificado 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 usando la etiqueta <sql:relationship> especificada. Cuando 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 de elemento <Order> subsiguientes de la misma forma.

  • Finalmente, el nodo de elemento <Customer> sale del ámbito. En ese momento, la carga masiva XML envía el registro del cliente a SQL Server. La carga masiva XML sigue este proceso para todos los clientes subsiguientes de la secuencia 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 al pedido están definidos 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, el elemento secundario <CustomerID> se especifica antes que el 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 estará disponible cuando el elemento <Order> entre 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, lo cual 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 ejemplo de Microsoft Visual Basic Scripting Edition (VBScript) siguiente (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, al igual que el tipo IDREFS.

Por ejemplo, fíjese en el esquema XSD siguiente que describe los elementos <Customer> y <Order>. El elemento <Customer> incluye un atributo OrderList de tipo IDREFS. La etiqueta <sql:relationship> especifica la relación de uno a varios entre el cliente y 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 de tipo IDREFS, no se produce 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, la especificación del elemento <Order> garantiza que la carga masiva XML agregue los registros de pedidos en la tabla Orders. El elemento <Order> describe todos los atributos que se exigen para completar el registro de la tabla CustOrder.

Debe asegurarse de que los valores de 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