最近のアクセス:
For Each コマンド (GeneXus X Evolution 2)
データベースからデータセットを取得するために使用する GeneXus のプロシージャー言語コマンドです。このコマンドは、プロシージャーのソース、Web パネルのイベント、およびサブルーチンで使用できます。プロシージャーで使用される場合には、データベースを読み取るだけでなく、更新することもできます。
For each コマンド内では、使用する項目属性の名前を指定して、読み取る情報 (Procedure オブジェクト内では書き込む情報も) を定義します。取得先のテーブルやアクセスに使用するインデックスを定義する必要はありません。必要な項目属性を定義すると、自動的に取得方法が決定されます。
顧客 (Customer) に関する情報の一部を表示するために、次のプロシージャーを設計します。
For each
    Print Customers
Endfor
「Customers」は、プロシージャー レイアウトで定義される次の printBlock の名前です:
イメージ:6022.jpg
上図から、前述の For each コマンド (顧客データを表示する Print コマンド文を含む) で、データベースにある各顧客 (Customer) のコード、名前、および国 (Country) を表示することが目的であると推測できます。
ここでは表示する項目属性を指定しただけですが、行われる操作が決定されています。
For each コマンドを記述した場合は必ず、データベースから何らかの情報を取得することが目的となります。そのため GeneXus では、For each コマンドがあれば、1 つのテーブル内をナビゲートし、そのテーブルの各レコードに関連する情報に対して何らかの処理を行う (印刷など) ことが目的であると判断します。
このため、すべての For each コマンドに対し、物理テーブルが 1 つナビゲートされます。このテーブルは「For each ベーステーブル」と呼ばれます。
上記の例で、GeneXus によりナビゲート対象として判定される For each ベーステーブルは、CUSTOMER です。各顧客の国は、COUNTRY テーブルから取得されます。
For each を定義する場合に、理解し考慮する必要がある重要な関連概念として、ベーステーブルの拡張テーブルがあります。
拡張テーブルの概念を理解すると、For each コマンドでベーステーブルがナビゲートされる一方で、そのベーステーブルの拡張テーブルに属するすべてのテーブルにアクセスして、必要な情報を取得できるということもわかります。上記の例でベース テーブルが CUSTOMER なのに、各顧客に関連する国を取得できるのは、このためです。COUNTRY テーブルが CUSTOMER の拡張テーブルに含まれているからです。
最後に、For each コマンドコード中に指定されている項目属性 (および呼び出されるプリントブロックで指定されている項目属性) に基づいて、それらすべての項目属性を含む最小限の拡張テーブルが検出され、その拡張テーブルのベーステーブルが For each ベーステーブルとして選択されます。

For each コマンドの構文例

For Each
   [ { [ order ]  order_attributesi  [ when condi ] }...|  [ order none ]   [ when condx ]  ] 
             [ using DataSelectorName( [   [ parm1  [ ,parm2  [ , ... ]  ] ) ]  
             [ {where {conditioni when condi} |
              {attribute IN DataSelectorName( [   [ parm1  [ ,parm2  [ , ... ]  ] } }... ] 
             [ defined by defined_attributes ] 
               [ Blocking NumericExpression ] 

             [ option distinct  ] 
                      code1
             [ when duplicate code2 ] 
             [ when none code3 ] 
EndFor
クエリの結果が返される順番を指定することができます。構文に示しているように、条件付き Order 節を多数記述できます。
Using 節:DataSelectorName という名前のデータ セレクター オブジェクトで指定されている条件に従ってフィルタリングします。

Where 節

conditioni :For Each で処理するデータが満たす必要のあるブール型の条件を指定します。「and」、「or」、「not」の論理演算子を使用した複合条件にすることもできます。この条件で指定する項目属性は、ベーステーブルと拡張テーブル1のどちらにあるものでもかまいません。
構文に示しているように、同じ For each に、連続 n 個の Where 節 (それぞれにフィルタリングの条件を含む) を指定することができます。
where cond1
where cond2
...
where condn
n 回目の where 節の出現は、連続するブール条件を持つ where 節が 1 つしか出現しない場合と同じです。つまり次のようになります:
where cond1 and cond2 and … and condn
クライアント/サーバープラットフォームでは、まず、各 where 節の when 節が評価され、条件が満たされた場合は、where 節で指定したフィルタが適用されます。
attribute IN DataSelectorName( [ parm1 [ ,parm2 [ , ... ] ] ):このデータ セレクター オブジェクトのクエリは、IN 演算子に先行する項目属性と同じ定義に対応する値のコレクションを返します。詳細は、「For Each グループにおけるデータセレクター」を参照してください。
1場合によっては、拡張テーブルに属さない項目属性が含まれることがあります。詳細は、「ヒントとしてのフィルタ」を参照してください。
Defined by 節:For each 項目属性を含む最小の拡張テーブルが複数ある場合があります。こうしたあいまいな状況では、最小の拡張テーブルのうち先頭にあるものが選択されます (その拡張テーブルのベーステーブルが、For each ベーステーブルに選択されます)。このあいまいさを解消するために、For each コマンドには Defined by 節があり、ナビゲート対象とするベーステーブルの項目属性を指定できます。Defined by節で指定する項目属性は、For each ベーステーブルを決定するための判断材料としてのみ使用されます。
Defined by 節には、目的のベーステーブルの項目属性を少なくとも 1 つ指定する必要があります。Defined by 節では、参照するベーステーブルのセカンダリー項目属性を指定することをお勧めします。これは、セカンダリー項目属性はモデルテーブルのみにあり、あいまいになることがないためです。ただし、これは強制ではありません。ベーステーブルの選択にあいまいさがないと分かっている場合には、Defined by 節でプライマリー項目属性を指定しても構いません。
一般的な誤認識に、For each に Defined by 節がある場合、For each ベーステーブルが Defined by 節で言及する項目属性から排他的に選択されるというものがあります。この節で指定した項目属性だけで、For each のベーステーブルが決まることはありません。Defined by 節で言及される項目属性は、特定の (または複数の) 物理テーブルに属します。このため、これらのテーブルも For each ベーステーブルになる可能性があります。ただし、(Defined by 節の項目属性に加えて) その他の For each 項目属性はすべて、候補となるテーブルが For each ベーステーブルとして選択されるように、そのテーブルの拡張テーブルに含まれている必要があります。つまり、(Order 節、Where 節、For each ボディ、印刷ブロック等で言及される) その他の For each 項目属性が候補となるテーブルの拡張テーブルに含まれていない場合、この候補テーブルが For each ベーステーブルに選択されることはありません。このため、指定時間に (拡張テーブルの概念を使って) For each で言及されるすべての項目属性にアクセスできるテーブルがない場合、ナビゲーションリストにはエラーと For each ベーステーブルを選択できないという説明が表示されます。
要するに、Defined by 節 は、(For each 項目属性を含む最小の拡張テーブルが複数ある場合) ベーステーブルを選択する際に生じるあいまいさの解消、あるいはほかの For each に含まれる項目属性で選択されるテーブルとは異なるベーステーブルを使用する必要がある場合に役に立つといえます。また、複雑なレポートの指定時間の改善にも使用されますが、広範囲に使用することは推奨しません。必要のないときにこの節を使用するデメリットは、テーブルの設計により多くのコードを固定することです。たとえば、COUNTRY テーブルを作成しておらず、セカンダリー項目属性が各顧客の所属する国であるとします。顧客とその国を一覧表示する必要がある場合、次のいずれかを実行すると同じ結果を得ることができます:
For each
    print Customers
EndFor
ここで、「Customers」は、CustomerId、CustomerName、および CountryName という項目属性を持つ printblock です。
For each
    defined by CountryName
    print Customers
EndFor
後から COUNTRY テーブルを作成することにし、CountryId を CUSTOMER の外部キーとして含める場合、最初の For each はそのまま有効で、所定の処理が継続される一方で、2 番目の For each は、Defined by 節にベーステーブルの項目属性がなくなるため動作しなくなります。指定時間にはまず、Defined by で指定されている項目属性が確認され、その項目属性が実際に含まれるテーブルが検出されて、これらのテーブルが For each ベース テーブルの候補として検討されます。このため、指定時間の改善を目的として、2 番目 の For each には Defined by 節が含まれています。ただし、このコードは CountryName が別のテーブルに移動するまで有効です。
Option distinct 節:参照される項目属性の値セットが一意であるレコードのみを返します。
Blocking 節:For each を使用して、拡張テーブルでクエリを実行するだけでなく、レコードを更新する場合、あるいはベーステーブルからレコードを削除する場合に適用されます。大量のレコードを更新または削除する必要があり、スループットが問題となる場合には、DBMS へのラウンドトリップを減らすことで解決できることがあります。
When duplicate:この節は、更新を処理する必要があるプロシージャーでのみ機能します。下記にその説明を示します。For each のボディ (code1) で、(一意のインデックスを持つ) 候補キーである項目属性を更新しようとした際に、その値を含むレコードが既に存在する場合に、この節が実行されます。一意のインデックスを使って、候補キーの一意性を確認します。また、複製が検出され、この節が For each コマンド内に書かれている場合、この節が含まれず、候補キーとなる項目属性と既に値を含むレコードを更新しようとする場合は、どのコードも実行されません。
When none:フィルタ条件に合致するデータがない場合、code1 コマンドは実行されません。代わりに code3 コード ブロックのコマンドが実行されます。
注:when duplicate および when none の両方について、For each コマンドが含まれる場合、when none | when duplicate を含む For each にジョインやフィルタは適用されません。それぞれ独立していると見なされます (上の例では、code1、code2、code3 固有)。

最適化

where 節のブール式は、取得されるデータセットを制限します。ただし、それだけではありません。フル スキャン テーブル アクセスとインデックスで最適化されたランダムアクセスには大きな違いがあります。一定の論理ルールを適用する場合、GeneXus は order 節(あるいはプライマリー キー オーダー)が、where ブール式と互換性があると判断します。フル テーブル スキャンを行わず、インデックスを使い、テーブルへのアクセスを最適化します。これは、どのような場合にも望ましい動作です。

スマートデバイスアプリケーション

For each コマンドは、SmartDevices ジェネレーターのアプリケーションの開発時に使用できますが、いくつか考慮事項があります。Work With for Smart Devices および Panel for Smart Devicesスマートデバイス用のシステムイベント (StartRefreshLoad の各イベント) でしか使用できません。

サブページ
Created: 14/09/18 03:13 by Admin Last update: 15/01/09 02:06 by Admin
カテゴリ
Powered by GXwiki 3.0