次の方法で共有


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

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

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

  1. マッピング スキーマを分析し、必要な実行プランを準備する。
  2. 実行プランを入力ストリームのデータに適用する。

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

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

ms172633.note(ja-jp,SQL.90).gifメモ :
注釈付き 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 属性が指定されています。<Customer> 要素は、sql:relation 注釈によって 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> 要素ごとにこの処理が行われます。

ms172633.note(ja-jp,SQL.90).gif重要 :
このモデルでは、終了タグに達した (ノードがスコープ外に出た) ときにレコードが挿入されるため、レコードに関連付けるすべてのデータをノードのスコープ内に定義する必要があります。

レコードのサブセットとキーの順序付け規則

<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 テーブルのレコードが生成されます。次に、<CustomerID><CompanyName>、および <City> 子要素がスコープ内に入ると、これらの要素から必要な列値 (CustomerID、CompanyName、および City) がコピーされます。
  • <Order> 要素ノードがスコープ内に入ると、XML 一括読み込みでは CustOrder テーブルのレコードが生成され、このレコードに OrderID 属性の値がコピーされます。CustomerID 列に必要な値は、<Customer> 要素の <CustomerID> 子要素から取得されます。XML 一括読み込みでは、<Order> 要素に CustomerID 属性が指定されていない限り、<sql:relationship> で指定された情報によって、このレコードの CustomerID 外部キー値が取得されます。一般的な規則としては、子要素で外部キー属性の値が明示的に指定されている場合、XML 一括読み込みではその値が使用され、指定された <sql:relationship> によって親要素から値が取得されることはありません。この <Order> 要素ノードがスコープ外に出ると、XML 一括読み込みではレコードが SQL Server に送信され、後続の <Order> 要素ノードがすべて同様に処理されます。
  • 最後に、<Customer> 要素ノードがスコープ外に出ると、XML 一括読み込みで顧客レコードが SQL Server に送信されます。XML 一括読み込みでは、XML データ ストリームの後続の顧客すべてについて、この処理が行われます。

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

  • 顧客と受注に関連付けられるすべてのデータが、<Customer> 要素ノードと <Order> 要素ノードに関連付けられるスコープ内に定義されているなど、スキーマが "構造的な" 規則を満たしている場合、一括読み込みは成功します。
  • <Customer> 要素を記述するとき、その子要素は適切な順序で指定されている必要があります。この場合、<CustomerID> 子要素は <Order> 子要素の前に指定されています。つまり、入力 XML データ ファイルで、<Order> 要素がスコープ内に入るとき、<CustomerID> 要素の値を外部キー値として使用できます。キー属性は最初に指定されます。これを "キーの順序付け規則" といいます。
    <CustomerID> 子要素を <Order> 子要素の後に指定した場合は、<Order> 要素がスコープ内に入ったとき、値を使用できません。</Order> 終了タグが読み取られると、CustOrder テーブルのレコードは完了したと判断され、CustOrder テーブルに挿入されますが、このとき CustomerID 列には NULL 値が挿入されます。これは想定した結果とは異なります。

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

  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 型のノードがスコープ内に入っても、ノードのレコードは生成されません。スキーマのどこかで、レコードを完全に記述するようにしてください。IDREFS 型が無視されるのと同様に、dt:type="nmtokens" 注釈は無視されます。

たとえば、次の XSD スキーマを考えてみます。このスキーマでは、<Customer> 要素と <Order> 要素が記述されており、<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