アソシエーション
アソシエーションは、2 つのビューどうしの関係のことであり、1 つのビューを別のビューにリンクする結合ビューのように機能します。この概念の詳細については、管理ガイドの「 アソシエーション 」を参照してください。
ここでは、アソシエーションを作成、変更、削除する VQL ステートメントについて説明します。
CREATE ASSOCIATION ステートメントの構文
CREATE [ OR REPLACE ] ASSOCIATION <identifier with database> [ REFERENTIAL CONSTRAINT ]
[ FOLDER = <folder:literal> ]
[ DESCRIPTION = <association_description:literal> ]
ENDPOINT <role_name:identifier> <view_name:identifier>
[ <mult:multiplicity> ]
[ PRECONDITION <condition> ]
[ DESCRIPTION = <endpoint_description:literal> ]
ENDPOINT <role_name:identifier> <view_name:identifier>
[<mult:multiplicity>]
[ PRECONDITION <condition> ]
[ DESCRIPTION = <endpoint_description:literal> ]
[ ADD MAPPING <val1:mapping_value> = <val1:mapping_value> ]+
<mapping_value> ::=
<field name>
| <mapping_value> <funcsymbol> <value>
| <value> <funcsymbol> <mapping_value>
| CASE <mapping_value>
WHEN <compare_value:value> THEN <result:value>
[ WHEN <compare_value:value> THEN <result:value> ]*
[ ELSE <result:value> ] END
| CASE WHEN <condition> THEN <result:value>
[ WHEN <condition> THEN <result:value> ]*
[ ELSE <result:value> ] END
<multiplicity> ::=
( 0 , 1 )
| ( 1 )
| ( * )
| ( + )
REFERENTIAL CONSTRAINT
句は、アソシエーションを参照制約として指定します (管理ガイドの「 アソシエーションの参照整合性 」を参照)。
1 番目の DESCRIPTION
句はアソシエーションの説明です。2 番目と 3 番目の同じ句は、アソシエーションの 2 つのエンドポイントの説明です。
PRECONDITIONS
句は、各エンドポイントの ロールの前提条件 を記述します (管理ガイドの「 ロールの前提条件 」を参照)。
ALTER ASSOCIATION ステートメントの構文
ALTER ASSOCIATION <name:identifier>
[ RENAME <new_name:identifier> ]
[ DESCRIPTION = <desc:literal> ]
アソシエーションの名前やその説明を変更するには ALTER ASSOCIATION
ステートメントを使用します。
アソシエーションを削除するには DROP ASSOCATION
ステートメントを実行します (「 DROP ステートメントの構文 」を参照)。
ナビゲーションクエリ
SELECT_NAVIGATIONAL
を使用して、ビューどうしに定義したアソシエーション間を移動 (ナビゲート) できるようにするクエリを実行できます。
ビューの特定の行をそのプライマリキーで同定し、そのビューの行にリンクしている、別のビューの行を取得するには、次の 2 つの方法があります。
アソシエーションを定義すると、結合の際に次のような利点が得られます。
クエリがきわめてシンプルになる。
アソシエーションの相手側のビューの名前をクライアントが把握する必要がない。
2 つのビューをリンクする有効な結合条件の作成方法をクライアントが把握する必要がない。
アソシエーションの相手側のビューやアソシエーションの条件を変更しても、クライアントに影響しない。
たとえば、ビュー「customer」とビュー「order」の間にアソシエーションがある場合、アプリケーションで SELECT_NAVIGATIONAL
ステートメントを実行して、特定の顧客 (customer) のすべての注文 (order) を取得できます。結合条件のフィールドの名前や、顧客の注文を保持するビューの名前を把握しておく必要はありません。
結合ではなく、アソシエーションを使用してこのような処理を実行する際の欠点は、結合のように 2 つのビューを複雑にリンクすることができないことです。
例
フィールド cid
をプライマリキーとするビュー customer
を考えます。このビューは、そのエンドポイントでのロールが orders
であるアソシエーションを構成しています。
SELECT_NAVIGATIONAL *
FROM customer / 2 / orders
WHERE o_description like '%Bandages%'
このクエリは、説明が Bandage
から始まる注文のうち、 cid = 2
である顧客によるものを返します。
このクエリと同等の SELECT
クエリは複雑になるうえ、JOIN 条件を構成するフィールドの名前がわかっている必要があります。以下に例を示します。
SELECT orders.*
FROM customer INNER JOIN orders
ON customer.cid = orders.cid
WHERE customer.cid = 2 AND orders.o_description like '%Bandages%'
SELECT_NAVIGATIONAL ステートメント (ナビゲーションクエリ) の構文
SELECT_NAVIGATIONAL <navigation fields>
FROM <view:identifier> [ <select navigations> ]
[ EXPAND <expand elements> ]
[ WHERE <extended condition> ]
[ GROUP BY <group by expression> [ , <group by expression> ]* ]
[ HAVING <extended condition> ]
[ ORDER BY <order by expression> [ ASC | DESC ] [, <order by expression> [ ASC | DESC ] ]* ]
[ WITH CONDITION MAPPINGS EVALUATION ]
[ FLATTEN FIRST LEVEL ROLES ]
[ OFFSET <number> [ ROW | ROWS ] ]
[
{
FETCH { FIRST | NEXT } [ <number> ] { ROW | ROWS } ONLY
| LIMIT [ <number> ]
}
]
[ CONTEXT ( <context information> [ , <context information> ]* ) ]
[ TRACE ]
<navigation fields> ::=
<navigation field> [, <navigation field> ]*
<navigation field> ::=
*
| <field:identifier> [ AS <alias:identifier> ]
| <role:identifier> / *
| <role:identifier> / <field:identifier>
| <function> ( [ <function parameter> ]* ) [ AS <alias:identifier> ]
| <expression>
<function parameter> ::=
<field:identifier>
| <simple navigation field>
<simple navigation field> ::=
<role:identifier> / <field:identifier>
<select navigations> ::=
/ <primary key values>
| / [ <condition> ]
| { / <primary key values> / <association:identifier> }*
[ / <primary key values> | / LBRACE <condition> RBRACE ]
<primary key values> ::=
<primary key value:value> [, <primary key value:value> ]*
<expand elements> ::=
<expand element> [ , <expand element> ]*
<expand element> ::=
<role:identifier> [ ( WHERE <regular condition:condition> ) ] [ / <role:identifier> [ ( WHERE <regular condition:condition> ) ] ]*
<group by expression> ::=
<field:identifier>
| <role:identifier> / <field:identifier>
| <expression>
| <function> ( [ <function parameter> ]* )
<order by expression> ::=
<expression>
| <field>
| <field position:integer>
| <role:identifier> / <field:identifier>
| <function> ( [ <function parameter> ]* )
このステートメントで最も重要な部分は、 FROM
句にあるナビゲーションの式です。これらの式では、クエリの適用対象となる 1 つまたは複数のエレメントの集合を特定しています。この集合として、ビュー、ビューの行、2 つのビューどうしのアソシエーションをたどって得られた結果などがあります。
WHERE
、 HAVING
、 ORDER BY
の各句では、ナビゲーションフィールド (role_customer/customer_name など) を使用できます。スカラー関数も使用でき、そのパラメータもナビゲーションフィールドとすることができます。以下に例を示します。
SELECT_NAVIGATIONAL order_id, order_date, concat( customer / company_name, ' - ', customer / contact_name) as company_contact, shipper / company_name
FROM order
EXPAND customer, shipper
WHERE UPPER(customer / "City") = 'LONDON'
FLATTEN FIRST LEVEL ROLES;
プライマリキーの要件
ビューにプライマリキーを定義している場合にのみ、ナビゲーションクエリはアソシエーションをたどることができます。管理ガイドの「 ビューのプライマリキー 」では、Administration Tool を使用してビューのプライマリキーを定義する方法について説明しています。「 CREATE TABLE ステートメントの構文 」と「 CREATE VIEW ステートメントの構文 」では、基本ビューと派生ビューを作成する際にプライマリキーを定義する VQL ステートメントの構文を取り上げています。
演算子 DIV (/)
「ナビゲーションフィールド」または式で除算演算子を使用する場合は DIV
を使用します。ロールをたどる操作を除き、ナビゲーションクエリでは /
は使用できません。
カーディナリティが多の場合
WHERE 句に、カーディナリティがエンドポイントに到達するナビゲーション フィールドがある場合、以下のように考えます。
1 つまたは複数の行が WHERE 条件を満たしている場合、条件は「true」になります。以下に例を示します。
SELECT_NAVIGATIONAL *, order_detail / *
FROM customer
EXPAND order_detail
WHERE order_detail / discount > 0.2
このクエリは、「order_detail」のうち「discount」が 0.2 より大きい 1 行または複数の行と関連付けられた「customer」テーブルの行を返します。
OR
条件内にこの条件を満たすナビゲーションフィールドが複数ある場合、そのナビゲーションフィールドは同じロールをたどる必要があります。次の例はサポートされています。
-- All the navigation fields traverse the role "emails".
WHERE POSITION('acme.com' IN emails / email) > 0 OR POSITION('denodo.com' IN emails / email)
しかし、次の条件は非ナビゲーションフィールド (city) が使用されているため、サポートされていません。
WHERE city = 'Los Angeles' OR POSITION('acme.com' IN emails / email) > 0
この制限は AND 条件には適用されません。次の例はサポートされています。
-- One field is not
WHERE city = 'Santiago de Compostela' AND POSITION('acme.com' IN emails / email) > 0
ロールに対するフィルタ条件
カーディナリティがエンドポイントに到達するロールを展開すると、それらのロールについて返される結果の集合をフィルタリングできます。例:
SELECT_NAVIGATIONAL *, order_detail / *
FROM customer
EXPAND order_detail ( WHERE discount > 0.1 )
このクエリは、テーブル「customer」のすべての行を返します。「order_detail」について返される値は、その「discount」が 0.1 より大きい値です。
以下の点に留意してください。
ロール「myrole」のフィルタ条件を定義する場合、「myrole」が到達するエンドポイントからのフィールドのみを使用します。そのような条件では、ナビゲーションフィールドは使用できません。つまり、以下のようなクエリは、条件が原因で無効になります。
SELECT_NAVIGATIONAL *, order_detail / *, order_detail / product_detail / *
FROM customer
EXPAND order_detail ( WHERE product_detail / warehouse_id = 132 ) / product_detail
ロール「myrole」のフィルタ条件を定義し、そのロールが EXPAND
句に複数回出現する場合、「myrole」のすべての出現箇所で同じフィルタ条件を定義します。例
SELECT_NAVIGATIONAL *, order_detail / product_detail / *, order_detail / incidence_detail / *
FROM customer
EXPAND order_detail ( WHERE discount > 0.1 ) / product_detail, order_detail ( WHERE discount > 0.1 ) / incidence_detail
その他のフィールド
SELECT_NAVIGATIONAL
クエリでは、 SELECT
句で指定したフィールドのほかに、次のような追加のフィールドが返されます。
ビューのアソシエーションごとに 1 つの追加フィールド。このフィールドの値は、以下のデータを収めたレジスターです。
このビューでプライマリキーを定義していれば、クエリの結果にフィールド _primary_key
が追加されます。
このフィールドには、クエリの結果にある各行を一意に識別するパス式が設定されます。このフィールドの値は、アソシエーションの各フィールドと構造が同じレジスターです。この例では、 rel
属性の値は必ず self
であり、パス式は絶対パスです。
「ORDER BY」の使用
クエリによって投影されるフィールドであれば ORDER BY
句に追加できます。
集約 (GROUP BY)
SELECT_NAVIGATIONAL は、展開フィールド (「customer_role / id」など) を伴う GROUP BY の実行をサポートしません。
例
以下に挙げる対象があるとします。
ビュー customer
: フィールド cid
をプライマリキーとします。
ビュー order
: フィールド oid
をプライマリキーとします。
両方のビューどうしのアソシエーション customer_orders
: ビュー customer
での、このアソシエーションのロール名を final_orders
とします。
以下に有効なナビゲーション式の例を示します。
クエリ |
説明 |
SELECT_NAVIGATIONAL *
FROM customer |
customer のすべての行が返されます。
|
SELECT_NAVIGATIONAL *
FROM customer / 1234 |
cid = 1234 である行が返されます。
プライマリキーを形成するフィールドの名前をクライアントが把握している必要はありません。
|
SELECT_NAVIGATIONAL *
FROM customer / 1234 / final_orders |
cid = 1234 である顧客によるすべての注文が返されます。
|
SELECT_NAVIGATIONAL *
FROM customer / 1234 / final_orders
/ 123 / products |
cid = 1234 である顧客による oid = 123 の注文で販売されたすべての製品が返されます。
|
SELECT_NAVIGATIONAL *
FROM customer / 1234 / final_orders
/ [ field <> 'value' ] |
cid = 1234 である顧客によるすべての注文のうち、条件 field <> 'value' に一致するものが返されます。
|
他の句 (SELECT
、 WHERE
、 ORDER BY
、 FETCH
、 OFFSET
) も、 SELECT
ステートメントの場合と同様に使用します。