2013年7月29日月曜日

GeneXusで生成されるJOINの種類

前回までで「開発者は項目属性名のみ指定する → GeneXusがアクセスするテーブル・JOINする項目を推論する」というお話しをしました。

SQLという観点で「GeneXusってOUTER JOINはできないよね?」という質問をよく受けます。そこで今回はGeneXusでのJOINに関するお話しです。

具体的なJOINの指定方法の前に、まずはGeneXusにおける基本的なJOINの考え方についてです。

1.GeneXusにおけるJOINの考え方


一般的にJOINは以下の種類があります。

  • 内部結合(INNER JOIN)
  • 外部結合(LEFT JOIN / RIGHT JOIN / FULL OUTER JOIN)


GeneXusにも外部結合は存在します。但し、ベーステーブル・拡張テーブルの考え方が前提になるため、リレーションの方向に依存します。どういう事でしょうか? 下記のデータモデルを見てください。






ベーステーブルを起点としてn→1方向のリレーションとなるテーブル(この例ではCustomer → Country) つまり拡張テーブルは内部結合(INNER JOIN)/外部結合(OUTER JOIN)を共にサポートします。

ベーステーブルを起点として1→n方向のリレーションとなるテーブル(この例ではCustomer → Invoice)は拡張テーブルではありませんので、外部結合は(そもそも内部結合も)対象となりません。


ここが通常開発でSQL文を手で記述する場合との大きな違いです。自分でSQL文を記述する場合は、リレーションの方向は気にせず外部結合の指定が可能です。

又、その為にLEFTとRIGHTという両方向の外部結合指定があります。一方、GeneXusはベーステーブルを起点としてn→1のリレーションに対する外部結合しかサポートしないので、LEFTのみの外部結合となります。(実際のSQL文[LEFT or OUTER]はDBMSによって変わります)



2.GeneXusでのJOINの指定方法


では、具体的に外部結合を実現する場合にどういう方法になるでしょうか?

実はアクセスする時の指定ではなく、データモデルの構造を定義する時つまりトランザクションオブジェクトのストラクチャー定義によって、内部結合か外部結合かが決定します。

・内部結合 : INNER JOIN(ディフォルト)
外部キー項目のNULLを許可しません。これは外部キー項目に必ず値をセットする必要があり、且つGeneXusでは参照整合性は絶対的な存在なので、値がセットされてる=JOINする対象レコードが存在する。という事になります。

トランザクションオブジェクトのストラクチャー定義にて
外部キー項目にNull不許可(ディフォルト)を指定


ビルド時のナビゲーションレポート
アイコンがイコールの場合は、INNER JOINが生成される





・外部結合 : OUTER JOIN
外部キー項目のNULLを許可します。これは外部キー項目に値をセットしない場合がある(NULL)のでOUTER JOINとなり、n側のテーブルの該当レコードは全て出力されます。


トランザクションオブジェクトのストラクチャー定義にて
外部キー項目にNull許可を指定

ビルド時のナビゲーションレポート
アイコンがチルダ(〜)の場合は、OUTER or LEFT JOINが生成される



3.[1→n]方向での外部結合

最後に、1→nのリレーションで外部結合してデータを取得したい場合はどうすればよいでしょうか?
例えば、ヘッダー・明細の伝票モデルで、明細レコードが存在しないケースも許容する場合に、ヘッダー項目・明細項目を一つのグリッドに並べて一覧表示する場合です。




この場合、GeneXusでは入れ子のfor each(nested for each)を使います。
つまり二重ループのfor eachを使い、外側のfor eachが1の側のテーブル、内側のfor eachがnの側のテーブルとすれば、nの側にJOINするレコードがあっても無くても1側のレコードを取得する事が可能になります。
入れ子のfor eachの記述例

ナビゲーションレポートでは
外側のfor eachがInvoiceテーブル(1側)
内側のfor eachがInvoiceDetail(n側)
と推論している



出典:Join Type and Join Location Specification

0 件のコメント:

コメントを投稿