Поделиться через


Процесс формирования записей (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')GOCREATE 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 = TrueobjBL.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')GOCREATE 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=TrueobjBL.Execute "c:\SampleSchema.xml", "c:\SampleXMLData.xml"set objBL=Nothing