Процесс создания записей (SQLXML 4.0)

Массовая загрузка XML обрабатывает входные XML-данные и готовит записи для соответствующих таблиц в Microsoft SQL Server. Логика массовой загрузки XML определяет, когда формируется новая запись, какие значения дочерних элементов или атрибута копировать в поля записи, и когда запись завершена и готова к отправке в SQL Server для вставки.

Массовая загрузка XML не загружает все входные XML-данные в память и не формирует полные наборы записей перед отправкой данных в SQL Server. Это объясняется тем, что входные XML-данные могут быть большим документом, и загрузка всего документа в память может быть дорогостоящей. Вместо этого массовая загрузка XML выполняет следующие действия.

  1. Анализирует схему сопоставления и готовит необходимый план выполнения.

  2. Применяет план выполнения к данным во входном потоке.

В связи с такой последовательной обработкой важно представить входные XML-данные определенным образом. Необходимо понимать, как массовая загрузка XML анализирует схему сопоставления и как происходит процесс создания записи. Это поможет предоставить схему сопоставления для массовой загрузки XML, которая даст нужные результаты.

Массовая загрузка XML обрабатывает общие заметки схемы сопоставления, в том числе сопоставления столбцов и таблиц (указанных явно с помощью заметок или неявно через сопоставление по умолчанию) и связи соединений.

ПримечаниеПримечание

Предполагается, что пользователь знаком со схемами сопоставления XSD и XDR с заметками. Дополнительные сведения о схемах см. в разделах Введение в схемы XSD с заметками (SQLXML 4.0) и Схемы XDR с заметками (устарели в SQLXML 4.0).

Чтобы понять процесс создания записей, необходимо понимать следующие концепции.

  • Область узла

  • Правило создания записей

  • Подмножество записей и правило упорядочения ключа

  • Исключения из правила создания записей

Область узла

Узел (элемент или атрибут) в XML-документе входит в область, когда массовая загрузка XML встречает его во входном потоке XML-данных. Для узла элемента открывающий тег элемента вводит элемент в область. Для узла атрибута имя атрибута вводит атрибут в область.

Узел выходит из области, когда в нем не остается данных: по закрывающему тегу (в случае узла элемента) или по окончанию значения атрибута (в случае узла атрибута).

Правило создания записей

Когда узел (элемент или атрибут) входит в область, появляется возможность формирования записи из этого узла. Запись существует так же долго, как связанный узел в области. Когда узел выходит из области, массовая загрузка XML рассматривает сформированную запись как завершенную (с данными) и отправляет ее в SQL Server для вставки.

Например, рассмотрим следующий фрагмент схемы 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>

Схема указывает элемент <Customer> с атрибутами CustomerID и CompanyName. Заметка sql:relation сопоставляет элемент <Customer> с таблицей Customers.

Рассмотрим следующий фрагмент XML-документа:

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

Когда массовой загрузке XML предоставляется схема, описанная в предыдущих абзацах, и XML-данные в качестве входных данных, она обрабатывает узлы (элементы и атрибуты) в источнике данных следующим образом.

  • Открывающий тег первого элемента <Customer> вводит этот элемент в область. Этот узел сопоставляется с таблицей Customers. Поэтому массовая загрузка XML формирует запись для таблицы Customers.

  • Все атрибуты элемента <Customer> в схеме сопоставляются столбцам таблицы Customers. По мере входа этих атрибутов в область, массовая загрузка XML копирует их значения в запись клиента, уже сформированную родительской областью.

  • Когда массовая загрузка XML достигает закрывающего тега для элемента <Customer>, элемент выходит из области. В результате массовая загрузка XML рассматривает запись как завершенную и отправляет ее в SQL Server.

Массовая загрузка XML выполняет этот процесс для каждого последующего элемента <Customer>.

Важное примечаниеВажно!

В этой модели, поскольку запись вставляется при достижении закрывающего тега (или выхода узла из области), необходимо определить все данные, связанные с записью в области узла.

Подмножество записей и правило упорядочения ключа

При указании схемы сопоставления, в которой используется заметка <sql:relationship>, термин «подмножество» относится к набору записей, сформированных на стороне внешнего ключа связи. В следующем примере записи таблицы CustOrder находятся на стороне внешнего ключа, <sql:relationship>.

Например, пусть база данных содержит следующие таблицы.

  • Cust (CustomerID, CompanyName, City);

  • CustOrder (CustomerID, OrderID).

Столбец CustomerID в таблице CustOrder является внешним ключом, под которым понимается первичный ключ CustomerID в таблице Cust.

Теперь рассмотрим представление XML, указанное в следующей схеме XSD с заметками. В этой схеме используется заметка <sql:relationship>, чтобы указать связь между таблицами Cust и 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>

Ниже приведен образец XML-данных и шаги для создания рабочего образца.

  • Когда узел элемента <Customer> в файле XML-данных входит в область, массовая загрузка XML формирует запись для таблицы Cust. Затем массовая загрузка XML копирует необходимые значения столбцов (CustomerID, CompanyName и City) из дочерних элементов <CustomerID>, <CompanyName> и <City>, по мере вхождения этих элементов в область.

  • Когда узел элемента <Order> входит в область, массовая загрузка XML формирует запись для таблицы CustOrder. Массовая загрузка XML копирует значения атрибута OrderID в эту запись. Значение, необходимое для столбца CustomerID, получается из дочернего элемента <CustomerID> элемента <Customer>. Массовая загрузка XML использует сведения, указанные в заметке <sql:relationship>, чтобы получить значение внешнего ключа CustomerID для этой записи, если только атрибут CustomerID не был указан в элементе <Order>. Общее правило: если дочерний элемент явно указывает значение для атрибута внешнего ключа, то массовая загрузка XML использует это значение и не получает значение из родительского элемента с помощью указанной заметки <sql:relationship>. При выходе этого узла элемента <Order> из области, массовая загрузка XML отправляет запись в SQL Server, а затем таким же образом обрабатывает все последующие узлы элемента <Order>.

  • Наконец, узел элемента <Customer> выходит из области. В это время массовая загрузка XML отправляет запись клиента в SQL Server. Массовая загрузка XML продолжает этот процесс для всех последующих клиентов в потоке XML-данных.

Два замечания о схеме сопоставления.

  • Если схема удовлетворяет правилу «включения» (например, все данные, связанные с клиентом и заказом, определяются в наборе связанных узлов элементов <Customer> и <Order>), массовая загрузка завершается успешно.

  • При описании элемента <Customer> его дочерние элементы указываются в соответствующем порядке. В этом случае дочерний элемент <CustomerID> указывается прежде дочернего элемента <Order>. Это значит, что во входном файле XML-данных значение элемента <CustomerID> доступно в качестве значения внешнего ключа, когда элемент <Order> входит в область. Первыми указываются ключевые атрибуты — это «правило упорядочения ключа».

    Если дочерний элемент <CustomerID> указан после дочернего элемента <Order>, значение недоступно, когда элемент <Order> входит в область. При последующем считывании закрывающего тега </Order>, запись для таблицы CustOrder считается завершенной и вставляется в таблицу CustOrder со значением NULL для столбца CustomerID, что нежелательно.

Создание рабочего образца

  1. Сохраните схему, приведенную в этом примере, в файле SampleSchema.xml.

  2. Создайте следующие таблицы.

    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. Сохраните следующий образец входных XML-данных в файле 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. Чтобы выполнить массовую загрузку XML-данных, сохраните следующий пример на языке 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
    

Исключения из правила создания записей

Массовая загрузка XML не формирует запись для узла, когда он входит в область, если этот узел типа IDREF или IDREFS. Необходимо убедиться, что в схеме приведено полное описание записи. Заметки dt:type="nmtokens" пропускаются так же, как пропускается тип IDREFS.

Например, рассмотрим следующий фрагмент схемы XSD, который описывает элементы <Customer> и <Order>. Элемент <Customer> включает атрибут OrderList типа IDREFS. Тег <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: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>

Поскольку массовая загрузка пропускает узлы типа IDREFS, записи не формируются, когда атрибут OrderList входит в область. Поэтому, если нужно упорядочить записи, добавленные в таблицу Orders, необходимо описать эти заказы в каком-то месте схемы. Указание элемента <Order> в этой схеме гарантирует, что массовая загрузка XML добавит записи заказов в таблицу Orders. Элемент <Order> описывает все атрибуты, необходимые, чтобы заполнить запись для таблицы CustOrder.

Необходимо обеспечить соответствие значений CustomerID и OrderID в элементе <Customer> и значений в элементе <Order>. Программист ответственен за обеспечение ссылочной целостности.

Проверка рабочего образца

  1. Создайте следующие таблицы.

    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. Сохраните схему сопоставления, приведенную в этом примере, в файле SampleSchema.xml.

  3. Сохраните следующий образец XML-данных в файле 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. Чтобы выполнить массовую загрузку XML-данных, сохраните этот пример на языке VBScript в файле Sample.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