FOR XML EXPLICIT を使用して、クエリが返す XML 文書の構造を制御できます。クエリは特定の方法で記述して、必要なネストに関する情報がクエリ結果内で指定されるようにしてください。FOR XML EXPLICIT がサポートするオプションのディレクティブを使用すると、個別のカラムの扱いを設定できます。たとえば、あるカラムが要素内容と属性内容のどちらとして表示されるかを制御できます。また、あるカラムが生成された XML に含まれるのではなく、結果の順序付けのみに使用されるように制御できます。
EXPLICIT モードでは、SELECT 文の最初の 2 つのカラムに、それぞれ名前 Tag と Parent を付けてください。Tag と Parent はメタデータカラムで、それらの値は、クエリが返す XML 文書内の要素の親子関係、またはネストを決定するために使用されます。
Tag カラム これは、SELECT リスト内で最初に指定されるカラムです。Tag カラムは、現在の要素のタグ番号を格納します。タグ番号として許可されている値は、1 から 255 までです。
Parent カラム このカラムは、現在の要素の親のタグ番号を格納します。このカラムの値が NULL の場合、そのローは XML 階層のトップレベルに位置付けられています。
たとえば、FOR XML EXPLICIT が指定されていない場合に、次の結果セットを返すクエリを考えてみます
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> |
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 結果を生成するときにこのカラムが無視されることを示します。このディレクティブは、テーブルを順序付ける目的のみに使用されるカラムを含めるために使用できます。属性名は無視され、結果には含まれません。
element カラム値が、属性としてではなく、名前 AttributeName を持つ、ネストされた要素として挿入されることを示します。
xml カラム値が、引用されずに挿入されることを示します。AttributeName が指定されている場合は、値はその名前を持つ要素として挿入されます。それ以外の場合は、値は、要素がラップされずに挿入されます。このディレクティブが使用されていない場合は、カラムが XML 型でないかぎり、マークアップ文字でエスケープされます。たとえば、値 <a/> は、&lt;a/&gt; として挿入されます。
cdata カラム値が CDATA セクションとして挿入されることを示します。AttributeName は無視されます。
BINARY、LONG BINARY、IMAGE、VARBINARY カラムのデータは、FOR XML EXPLICIT を含むクエリを実行すると、自動的に Base64 エンコードフォーマットで返されます。デフォルトでは、結果セット内のすべての NULL 値は省略されます。for_xml_null_treatment オプションの設定を変更すると、この動作を変更できます。
次の 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 クエリを構成する方法を説明します。
トップレベルの要素を生成する 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; |
子要素を生成する 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 |
クエリに UNION DISTINCT を追加して、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 DISTINCT SELECT 2, 1, EmployeeID, CustomerID, Region FROM Employees KEY JOIN SalesOrders |
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 DISTINCT SELECT 2, 1, EmployeeID, CustomerID, Region FROM Employees KEY JOIN SalesOrders ORDER BY 3, 1 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 DISTINCT SELECT 2, 1, EmployeeID, NULL, OrderDate, NULL FROM Employees KEY JOIN SalesOrders UNION DISTINCT 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 & D"/> </employee> <employee id="105" name="Matthew"> <department name="R & 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 ディレクティブを追加します。
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 DISTINCT SELECT 2, 1, EmployeeID, NULL, OrderDate, NULL FROM Employees KEY JOIN SalesOrders UNION DISTINCT 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 & D</name> </department> </employee> <employee> <id>105</id> <name>Matthew</name> <department> <name>R & 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> ... |
次のクエリでは、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 DISTINCT SELECT 2, 1, EmployeeID, NULL, OrderDate, NULL FROM Employees KEY JOIN SalesOrders UNION DISTINCT 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 & D"/> </employee> <employee name="Matthew"> <department name="R & 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> ... |
デフォルトでは、FOR XML EXPLICIT クエリの結果に XML 文字として有効ではない文字が含まれる場合、カラムが XML 型でないかぎり、無効な文字はエスケープされます。詳細は、不正な XML 名のエンコーディングを参照してください。
たとえば、次のクエリは、アンパサンド (&) を含む XML を生成します。
SELECT 1 AS tag, NULL AS parent, ID AS [customer!1!id!element], CompanyName AS [customer!1!company!element] FROM Customers WHERE ID = '115' FOR XML EXPLICIT; |
このクエリによって生成される結果では、アンパサンドはエスケープされます。これは、このカラムが XML 型ではないためです。
<customer><id>115</id> <company>Sterling & Co.</company> </customer> |
xml ディレクティブは、生成される XML にカラム値がエスケープされずに挿入されることを示します。前述のクエリに xml ディレクティブを付けて実行します。
SELECT 1 AS tag, NULL AS parent, ID AS [customer!1!id!element], CompanyName AS [customer!1!company!xml] FROM Customers WHERE ID = '115' FOR XML EXPLICIT; |
結果内で、アンパサンドはエスケープされていません。
<customer> <id>115</id> <company>Sterling & Co.</company> </customer> |
この XML は、アンパサンドが含まれるため、整形式ではない点に注意してください。アンパサンドは、XML においては特別な文字です。クエリを使用して XML を生成する場合は、その XML が整形式であり、妥当であることを確認してください。SQL Anywhere は、生成される XML が整形式または妥当であるかをチェックしません。
xml ディレクティブを指定すると、AttributeName フィールドは属性ではなく要素を生成するために使用されます。
次のクエリは、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> ... |
![]() |
DocCommentXchange で意見交換できます
|
Copyright © 2012, iAnywhere Solutions, Inc. - SQL Anywhere 12.0.1 |