レコードの生成処理 (SQLXML 4.0)

適用対象: SQL Server Azure SQL Database

XML 一括読み込みでは、XML 入力データが処理され、Microsoft SQL Server の適切なテーブルのレコードが準備されます。 XML 一括読み込みのロジックは、新しいレコードを生成するタイミング、レコードのフィールドにコピーする子要素または属性値、およびレコードが完了し、挿入のために SQL Server に送信する準備ができているタイミングを決定します。

XML 一括読み込みでは、XML 入力データ全体がメモリに読み込まれることはありません。また、SQL Server にデータを送信する前に完全なレコード セットが生成されることはありません。 これは、XML 入力データが大きなドキュメントの場合に、ドキュメント全体をメモリに読み込むと時間がかかる可能性があるためです。 代わりに、XML 一括読み込みでは次の操作が行われます。

  1. マッピング スキーマを分析し、必要な実行プランを準備する。

  2. 実行プランを入力ストリームのデータに適用する。

この順次処理では、決まった方法で XML 入力データを指定することが重要です。 また、XML 一括読み込みでマッピング スキーマがどのように分析されるかと、レコード生成処理がどのように行われるかについて理解しておく必要があります。 これらを理解しておくと、XML 一括読み込みに対し、必要な結果を生成するマッピング スキーマを指定できます。

XML 一括読み込みでは、注釈により明示的に、または既定のマッピングにより暗黙的に行われる列とテーブルのマッピングを含む一般的なマッピング スキーマ注釈、および結合リレーションシップが処理されます。

Note

注釈付き XSD または XDR マッピング スキーマについて理解していることを前提としています。 スキーマの詳細については、「 注釈付き XSD スキーマへの導入 (SQLXML 4.0) または Annotated 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>  

スキーマは、CustomerID 属性と CompanyName 属性を持つ <Customer> 要素を指定します。 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)

CustOrder テーブルの CustomerID は、Cust テーブルの CustomerID 主キーを参照する外部キーです。

ここで、次の注釈付き XSD スキーマで指定される XML ビューを考えてみます。 このスキーマでは、 <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 データと、実際のサンプルを作成する手順は次のとおりです。

  • XML データ ファイルの <Customer> 要素ノードがスコープに入ると、XML 一括読み込みによって Cust テーブルのレコードが生成されます。 XML 一括読み込みでは、 <CustomerID><CompanyName>、および <City> 子要素から必要な列値 (CustomerID、CompanyName、および City) がコピーされます。

  • <Order>要素ノードがスコープに入ると、XML 一括読み込みによって CustOrder テーブルのレコードが生成されます。 XML 一括読み込みでは、 OrderID 属性の値がこのレコードにコピーされます。 CustomerID 列に必要な値は、<Customer> 要素の <CustomerID> 子要素から取得されます。 XML 一括読み込みでは、CustomerID 属性が <Order> 要素で指定されていない限り、<sql:relationship> で指定された情報を使用してこのレコードの CustomerID 外部キー値を取得します。 一般的な規則では、子要素が外部キー属性の値を明示的に指定した場合、XML 一括読み込みではその値が使用され、指定された <sql:relationship> を使用して親要素から値が取得されることはありません。 この <Order> 要素ノードがスコープ外になると、XML 一括読み込みによってレコードが SQL Server に送信され、後続のすべての <Order> 要素ノードが同じ方法で処理されます。

  • 最後に、 <Customer> 要素ノードがスコープ外になります。 その時点で、XML 一括読み込みによって顧客レコードが SQL Server に送信されます。 XML 一括読み込みでは、XML データ ストリームの後続の顧客すべてについて、この処理が行われます。

マッピング スキーマに関しては、次の 2 つの点に注意してください。

  • スキーマが "包含" ルールを満たしている場合 (たとえば、顧客に関連付けられているすべてのデータが、関連付けられた <Customer> および <Order> 要素ノードのスコープ内で定義されている場合)、一括読み込みが成功します。

  • <Customer>要素を記述する場合、その子要素は適切な順序で指定されます。 この場合、 <CustomerID> 子要素は、 <Order> 子要素の前に指定されます。 つまり、入力 XML データ ファイルでは、 <CustomerID> 要素の値は、 <Order> 要素がスコープに入ったときに外部キー値として使用できます。 キー属性は最初に指定されます。これを "キーの順序付け規則" といいます。

    <Order> 子要素の後に <CustomerID> 子要素を指定した場合、<Order> 要素がスコープに入ったときに値は使用できません。 </Order>終了タグを読み取ると、CustOrder テーブルのレコードが完了したと見なされ、CustomerID 列の NULL 値を持つ CustOrder テーブルに挿入されます。これは目的の結果ではありません。

実際のサンプルを作成するには

  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 型が無視されるのと同じように無視されます。

たとえば、 <Customer> および <Order> 要素について説明する次の XSD スキーマについて考えてみます。 <Customer> 要素には、IDREFS 型の OrderList 属性が含まれています。 <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 テーブルのレコードを入力するために必要なすべての属性を記述します。

<Customer> 要素の CustomerID および OrderID 値が、<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 の例 (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