Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (日本語) » SQL Anywhere サーバ - SQL の使用法 » データベースにおける XML » データベースにおける XML の使用 » クエリ結果を XML として取得する

 

FOR XML EXPLICIT の使用

FOR XML EXPLICIT を使用して、クエリが返す XML 文書の構造を制御できます。クエリは特定の方法で記述して、必要なネストに関する情報がクエリ結果内で指定されるようにしてください。FOR XML EXPLICIT がサポートするオプションのディレクティブを使用すると、個別のカラムの扱いを設定できます。たとえば、あるカラムが要素内容と属性内容のどちらとして表示されるかを制御できます。また、あるカラムが生成された XML に含まれるのではなく、結果の順序付けのみに使用されるように制御できます。

FOR XML EXPLICIT を使用してクエリを記述する方法の例は、EXPLICIT モードのクエリの記述を参照してください。

パラメータ

EXPLICIT モードでは、SELECT 文の最初の 2 つのカラムに、それぞれ名前 TagParent を付けてください。Tag と Parent はメタデータ・カラムで、それらの値は、クエリが返す XML 文書内の要素の親子関係、またはネストを決定するために使用されます。

  • Tag カラム   これは、select リスト内で最初に指定されるカラムです。Tag カラムは、現在の要素のタグ番号を格納します。タグ番号として許可されている値は、1 から 255 までです。

  • Parent カラム   このカラムは、現在の要素の親のタグ番号を格納します。このカラムの値が NULL の場合、そのローは XML 階層のトップ・レベルに位置付けられています。

たとえば、FOR XML EXPLICIT が指定されていない場合に、次の結果セットを返すクエリを考えてみます(GivenName!1 と ID!2 データ・カラムの目的は、次のクエリへのデータ・カラムの追加で説明します)。

Tag Parent GivenName!1 ID!2
1 NULL 'Beth' NULL
2 NULL NULL '102'

この例では、Tag カラムの値は、結果セット内の各要素のタグ番号です。両方のローの Parent カラムには、値 NULL が含まれています。これは、両要素とも階層のトップ・レベルに生成されることを意味し、クエリに FOR XML EXPLICIT 句が含まれる場合は、次の結果が得られます。

<GivenName>Beth</GivenName>
<ID>102</ID>

しかし、2 番目のローの Parent カラムが値 1 を持つ場合は、結果は次のようになります。

<GivenName>Beth
   <ID>102</ID>
</GivenName>

FOR XML EXPLICIT を使用してクエリを記述する方法の例は、EXPLICIT モードのクエリの記述を参照してください。

クエリへのデータ・カラムの追加

Tag カラムと Parent カラムに加えて、クエリには、1 つ以上のデータ・カラムを含めてください。これらのデータ・カラムの名前は、タグ付け中にカラムが解釈される方法を制御します。各カラム名は、感嘆符 (!) で区切られるフィールドに分割されます。次のフィールドをデータ・カラムに指定できます。

ElementName!TagNumber!AttributeName!Directive

ElementName   要素の名前。ある特定のローに関して、ローに対して生成される要素名は、一致するタグ番号を持つ最初のカラムの ElementName フィールドから取得されます。同じ TagNumber を持つ複数のカラムがある場合は、ElementName は、同じ TagNumber を持つ後続のカラムについては無視されます。前述の例では、最初のローは、<GivenName> と呼ばれる要素を生成します。

TagNumber   要素のタグ番号。ある特定のタグ値を持つローに関して、TagNumber フィールドに同じ値を持つすべてのカラムは、そのローに対応する要素に内容を提供します。

AttributeName   カラム値が ElementName 要素の属性であることを指定します。たとえば、データ・カラムが productID!1!Color という名前の場合、Color は <productID> 要素の属性として表示されます。

Directive   このオプション・フィールドを使用して、XML 文書のフォーマットをさらに制御できます。Directive に対して次の値のいずれか 1 つを指定できます。

  • hide   このカラムが、結果を生成する目的で無視されることを示します。このディレクティブは、テーブルを順序付ける目的のみに使用されるカラムを含めるために使用できます。属性名は無視され、結果には含まれません。

    hide ディレクティブの使用例については、hide ディレクティブの使用を参照してください。

  • element   カラム値が、属性としてではなく、名前 AttributeName を持つ、ネストされた要素として挿入されることを示します。

    element ディレクティブの使用例については、element ディレクティブの使用を参照してください。

  • xml   カラム値が、引用されずに挿入されることを示します。AttributeName が指定されている場合は、値はその名前を持つ要素として挿入されます。それ以外の場合は、値は、要素がラップされずに挿入されます。このディレクティブが使用されていない場合は、カラムが XML 型でないかぎり、マークアップ文字でエスケープされます。たとえば、値 <a/> は、&lt;a/&gt; として挿入されます。

    xml ディレクティブの使用例については、xml ディレクティブの使用を参照してください。

  • cdata   カラム値が CDATA セクションとして挿入されることを示します。AttributeName は無視されます。

    cdata ディレクティブの使用例については、cdata ディレクティブの使用を参照してください。

使用法

BINARY、LONG BINARY、IMAGE、VARBINARY カラムのデータは、FOR XML EXPLICIT を含むクエリを実行すると、自動的に Base64 エンコード・フォーマットで返されます。デフォルトでは、結果セット内のすべての NULL 値は省略されます。for_xml_null_treatment オプションの設定を変更すると、この動作を変更できます。

for_xml_null_treatment オプションの詳細については、for_xml_null_treatment オプション [データベース]FOR XML と NULL 値を参照してください。

EXPLICIT モードのクエリの記述

次の XML 文書を生成するクエリを FOR XML EXPLICIT を使用して記述するとします。

<employee EmployeeID='129'>
   <customer CustomerID='107' Region='Eastern'/>
   <customer CustomerID='119' Region='Western'/>
   <customer CustomerID='131' Region='Eastern'/>
</employee>
<employee EmployeeID='195'>
   <customer CustomerID='109' Region='Eastern'/>
   <customer CustomerID='121' Region='Central'/>
</employee>

このためには、次の結果セットを指定された順序どおりに返す SELECT 文を記述し、クエリに FOR XML EXPLICIT を追加します。

Tag Parent employee!1!EmployeeID customer!2!CustomerID customer!2!Region
1 NULL 129 NULL NULL
2 1 129 107 Eastern
2 1 129 119 Western
2 1 129 131 Central
1 NULL 195 NULL NULL
2 1 195 109 Eastern
2 1 195 121 Central

クエリを記述すると、ある特定のローの一部のカラムのみが、生成された XML 文書の一部となります。カラムは、TagNumber フィールド (カラム名の 2 つめのフィールド) の値が、Tag カラムの値と一致する場合のみ、XML 文書に含められます。

この例では、Tag カラムに値 1 を持つ 2 つのローの場合に 3 番目のカラムが使用されます。4 番目と 5 番目のカラムでは、Tag カラムに値 2 を持つローの場合に値が使用されます。要素名は、カラム名の最初のフィールドから取得されます。この例の場合、<employee> 要素と <customer> 要素が作成されます。

属性名は、カラム名の 3 番目のフィールドから取得されます。したがって、<employee> 要素に対して EmployeeID 属性が作成され、<customer> 要素に対して CustomerID 属性と Region 属性が作成されます。

次の手順では、SQL Anywhere サンプル・データベースを使用して、この項の最初にある XML 文書に似た XML 文書を生成する FOR XML EXPLICIT クエリを構成する方法を説明します。

♦  FOR XML EXPLICIT クエリを記述するには、次の手順に従います。
  1. トップ・レベルの要素を生成する SELECT 文を記述します。

    この例では、クエリの最初の SELECT 文は、<employee> 要素を生成します。クエリの最初の 2 つの値は、Tag カラム値と Parent カラム値にしてください。<employee> 要素は、階層のトップにあるため、Tag 値に 1 を、Parent 値に NULL を割り当ててください。

    注意

    UNION を使用する EXPLICIT モードのクエリを記述する場合、最初の SELECT 文で指定されたカラム名のみが使用されます。要素名または属性名として使用するカラム名は、最初の SELECT 文で指定してください。これは、後続の SELECT 文で指定されたカラム名は無視されるためです。

    前述のテーブルの <employee> 要素を生成するためには、最初の SELECT 文は、次のようになります。

    SELECT
          1          AS tag,
          NULL       AS parent,
          EmployeeID AS [employee!1!EmployeeID],
          NULL       AS [customer!2!CustomerID],
          NULL       AS [customer!2!Region]
    FROM Employees;
  2. 子要素を生成する SELECT 文を記述します。

    2 つめのクエリは、<customer> 要素を生成します。これは EXPLICIT モード・クエリのため、すべての SELECT 文において、最初の 2 つの値に Tag 値と Parent 値を指定してください。<customer> 要素には、タグ番号 2 を与えます。また、この要素は <employee> 要素の子であるため、Parent 値は 1 になります。最初の SELECT 文で、すでに EmployeeID、CustomerID、Region は属性であると指定しています。

    SELECT
          2,
          1,
          EmployeeID,
          CustomerID,
          Region
    FROM Employees KEY JOIN SalesOrders
  3. クエリに UNION ALL を追加して、2 つの SELECT 文を結合します。

    SELECT
          1          AS tag,
          NULL       AS parent,
          EmployeeID AS [employee!1!EmployeeID],
          NULL       AS [customer!2!CustomerID],
          NULL       AS [customer!2!Region]
    FROM Employees
    UNION ALL 
    SELECT
          2,
          1,
          EmployeeID,
          CustomerID,
          Region
    FROM Employees KEY JOIN SalesOrders
  4. ORDER BY 句を追加して、結果内のローの順序を指定します。ローの順序は、生成される文書内で使用される順序です。

    SELECT
          1          AS tag,
          NULL       AS parent,
          EmployeeID AS [employee!1!EmployeeID],
          NULL       AS [customer!2!CustomerID],
          NULL       AS [customer!2!Region]
    FROM Employees
    UNION ALL 
    SELECT
          2,
          1,
          EmployeeID,
          CustomerID,
          Region
    FROM Employees KEY JOIN SalesOrders
    ORDER BY 3, 1
    FOR XML EXPLICIT;

EXPLICIT モードの構文については、パラメータを参照してください。

FOR XML EXPLICIT の例

次のクエリ例は、従業員による発注に関する情報を取り出します。この例では、<employee>、<order>、<department> という 3 種類の要素があります。<employee> 要素は ID 属性と name 属性を持ち、<order> 要素は date 属性を、また <department> 要素は name 属性を持ちます。

SELECT
        1           tag,
        NULL        parent,
        EmployeeID  [employee!1!ID],
        GivenName   [employee!1!name],
        NULL        [order!2!date],
        NULL        [department!3!name]
FROM Employees
UNION ALL 
SELECT
        2,
        1,
        EmployeeID,
        NULL,
        OrderDate,
        NULL
FROM Employees KEY JOIN SalesOrders
UNION ALL 
SELECT
        3,
        1,
        EmployeeID,
        NULL,
        NULL,
        DepartmentName
FROM Employees e JOIN Departments d
   ON e.DepartmentID=d.DepartmentID
ORDER BY 3, 1
FOR XML EXPLICIT;

このクエリから次の結果が得られます。

<employee ID="102" name="Fran">
   <department name="R &amp; D"/>
</employee>
<employee ID="105" name="Matthew">
   <department name="R &amp; D"/>
</employee> 
<employee ID="129" name="Philip">
   <order date="2000-07-24"/>
   <order date="2000-07-13"/>
   <order date="2000-06-24"/>
   <order date="2000-06-08"/>
   ...
   <department name="Sales"/>
</employee> 
<employee ID="148" name="Julie">
   <department name="Finance"/>
</employee>
...
element ディレクティブの使用

属性ではなくサブ要素を生成する場合は、次のように、クエリに element ディレクティブを追加します。

SELECT
        1          tag,
        NULL       parent,
        EmployeeID [employee!1!id!element],
        GivenName  [employee!1!name!element],
        NULL       [order!2!date!element],
        NULL       [department!3!name!element]
FROM Employees 
UNION ALL
SELECT
        2,
        1,
        EmployeeID,
        NULL,
        OrderDate,
        NULL
FROM Employees KEY JOIN SalesOrders
UNION ALL 
SELECT
        3,
        1,
        EmployeeID,
        NULL,
        NULL,
        DepartmentName
FROM Employees e JOIN Departments d
   ON e.DepartmentID=d.DepartmentID
ORDER BY 3, 1
FOR XML EXPLICIT;

このクエリから次の結果が得られます。

<employee>
   <id>102</id>
   <name>Fran</name>
   <department>
      <name>R &amp; D</name>
   </department>
</employee> 
<employee>
   <id>105</id>
   <name>Matthew</name>
   <department>
      <name>R &amp; D</name>
   </department>
</employee> 
<employee>
   <id>129</id>
   <name>Philip</name>
   <order>
      <date>2000-07-24</date>
   </order>
   <order>
      <date>2000-07-13</date>
   </order>
   <order>
      <date>2000-06-24</date>
   </order>
   ...
   <department>
      <name>Sales</name>
   </department>
</employee>
...
hide ディレクティブの使用

次のクエリでは、employee ID は、結果の順序付けに使用されていますが、hide ディレクティブが指定されているため、結果には表示されません。

SELECT
        1           tag,
        NULL        parent,
        EmployeeID  [employee!1!id!hide],
        GivenName   [employee!1!name],
        NULL        [order!2!date],
        NULL        [department!3!name]
FROM Employees
UNION ALL 
SELECT
        2,
        1,
        EmployeeID,
        NULL,
        OrderDate,
        NULL
FROM Employees KEY JOIN SalesOrders
UNION ALL 
SELECT
        3,
        1,
        EmployeeID,
        NULL,
        NULL,
        DepartmentName
FROM Employees e JOIN Departments d
   ON e.DepartmentID=d.DepartmentID
ORDER BY 3, 1
FOR XML EXPLICIT;

このクエリは、次の結果を返します。

<employee name="Fran">
   <department name="R &amp; D"/>
</employee>
<employee name="Matthew">
   <department name="R &amp; D"/>
</employee> 
<employee name="Philip">
   <order date="2000-04-21"/>
   <order date="2001-07-23"/>
   <order date="2000-12-30"/>
   <order date="2000-12-20"/>
   ...
   <department name="Sales"/>
</employee> 
<employee name="Julie">
   <department name="Finance"/>
</employee>
...
xml ディレクティブの使用

デフォルトでは、FOR XML EXPLICIT クエリの結果に XML 文字として有効ではない文字が含まれる場合、カラムが XML 型でないかぎり、無効な文字はエスケープされます (詳細については、不正な XML 名のエンコーディングを参照)。たとえば、次のクエリは、アンパサンド (&) を含む XML を生成します。

SELECT
        1              AS tag,
        NULL           AS parent,
        ID             AS [customer!1!ID!element],
        CompanyName    AS [customer!1!CompanyName]
FROM Customers
WHERE ID = '115'
FOR XML EXPLICIT;

このクエリによって生成される結果では、アンパサンドはエスケープされます。これは、このカラムが XML 型ではないためです。

<Customers CompanyName="Sterling &amp; Co.">
   <ID>115</ID>
</Customers>

xml ディレクティブは、生成される XML にカラム値が引用されずに挿入されることを示します。前述のクエリに xml ディレクティブを付けて実行します。

SELECT
        1              AS tag,
        NULL           AS parent,
        ID             AS [customer!1!ID!element],
        CompanyName    AS [customer!1!CompanyName!xml]
FROM Customers
WHERE ID = '115'
FOR XML EXPLICIT;

結果内で、アンパサンドは引用されていません。

<customer>
 <ID>115</ID>
 <CompanyName>Sterling & Co.</CompanyName>
</customer>

この XML は、アンパサンドが含まれるため、整形式ではない点に注意してください。アンパサンドは、XML においては特別な文字です。クエリを使用して XML を生成する場合は、その XML が整形式であり、妥当であることを確認してください。SQL Anywhere は、生成される XML が整形式または妥当であるかをチェックしません。

xml ディレクティブを指定すると、AttributeName フィールドは無視され、属性ではなく要素が生成されます。

cdata ディレクティブの使用

次のクエリは、cdata ディレクティブを使用して、製品名を CDATA セクションに入れて返します。

SELECT
        1               AS tag,
        NULL            AS parent,
        ID              AS [product!1!ID],
        Description     AS [product!1!!cdata]
FROM Products
FOR XML EXPLICIT;

このクエリによって生成される結果は、各製品の説明を CDATA セクション内にリストします。CDATA セクションに含まれるデータは、引用されません。

<product ID="300">
   <![CDATA[Tank Top]]>
</product>
<product ID="301">
   <![CDATA[V-neck]]>
</product> 
<product ID="302">
   <![CDATA[Crew Neck]]>
</product>
<product ID="400">
   <![CDATA[Cotton Cap]]>
</product>
...