プロシージャーには、テーブルにレコードを挿入するための New という名前のコマンドがあります。このコマンドを使用することで、
1 つの物理テーブルの項目属性に値を割り当てることができます。

テーブルに
新しいレコードを挿入するための低レベルコマンドです。新しいレコードはデータベースを変更するので、
Procedure オブジェクトにだけ適しています。異なる方法で追加を実行する
Transaction オブジェクトには適していません。
注: Breogán Gonda と Nicolás Jodal 共著の「
GeneXus and Relational Databases: the Essence」を参照してください。
システムで管理している製品の情報を、対応する価格表とともに格納するための Product トランザクションがあります。構造は次のとおりです:
Product
{
ProductId*
ProductDescription
ProductStock
PriceList
{
ProductPriceListDate*
ProductPriceListPrice
}
}
これをベースに、GeneXus は次の 2 つのテーブルを作成します: 構造内のレベルに対応する PRODUCT テーブルと PRODUCTPRICELIST テーブル。PRODUCTPRICELIST テーブルには、次の 3 つのテーブルを作成します:
主キー {ProductId, ProductPriceListDate} を持つ、ProductId、ProductPriceListDate、および ProductPriceListPrice。
製品の ID をパラメーターとして受け取り、プロシージャーを実行した日付の新しい価格 (これもパラメーターとして受け取る) を価格表に追加する
Procedure オブジェクトを実装するとします。したがって、プロシージャーの [ Rules ] エレメントには次が含まれます:
Parm( in: &ProductId, in:&price );
[ Source ] エレメントに次のように入力します:
New
ProductId = &ProductId
ProductPriceListDate = &Today
ProductPriceListPrice = &price
EndNew
New コマンド内には割り当てコマンドがあり、ここでレコードを挿入しようとしているテーブル内の各項目属性に対して値が割り当てられます。ここでは、PRODUCTPRICELIST テーブルにレコードを追加します。
「
この例の背景となっているコンセプトの詳細説明」も参照してください。
New
[ Defined by attributeList ]
[ Blocking NumericExpression ]
BodyCode
[ When duplicate
{ AnotherCode |
For each
{att = exp}
…
Endfor
| AnotherCode } ]
EndNew
入力値の説明:
attributeList
レコードを追加するテーブルを (
BodyCode の内部にある割り当ての左側の項目属性とともに) 決定する項目属性のリスト (コンマまたはスペース区切り) です。
NumericExpression
「ブロッキング因数」です。この節により、
ブロック (バッチ) 挿入メカニズムが有効となり、ブロックごとに追加するレコードの数をコントロールします。
BodyCode
コマンドのシーケンスです。ほとんどが次の形式になります (すべてではありません):
att = exp
入力値の説明:
att
追加するレコードに割り当てる項目属性です。
exp
項目属性、変数、定数、関数、および演算式 (Date および Numeric のタイプのみ) を割り当て可能です。
重複するレコードが検出された場合 (同一の
主キーまたは
候補キーを持つレコードがテーブルに既に存在する場合) に実行するコードを指定します。ほとんどの場合、その既存のレコードの一部の項目属性の更新が必要になります。このような場合は
For Each コマンドを使用する必要があり、その内部で更新する項目属性が割り当てられます。あまり一般的ではありませんが、ほかのコマンドを実行することもできます (
AnotherCode)。
注: Blocking 節がある場合、ブロック全体の挿入を試行したときに重複するレコードが見つかると、
When Duplicate コマンドが実行されます。この場合、ブロック内の各レコードに対して挿入が試行され、すべてのレコードが正常に挿入されるか、When Duplicate コマンドが実行されます。詳しい説明は、「
ブロック (バッチ) 挿入メカニズム」を参照してください。
ここでは、
拡張テーブルのコンセプトは使用されていません。このコマンドは、単一の物理テーブルに、
BodyCode の項目属性および Defined by 節の内容 (妥当な場合) によって決定される単一のレコードを追加することで動作します。
主キー、
候補キーの重複キーがチェックされます。コマンドに
Blocking 節がある場合でも、単一のテーブルに単一のレコードが追加されます。Blocking 節は、New コマンドがループ内ではなく繰り返し構造内にある場合にのみパフォーマンスを向上させることができます。
ベーステーブルに属さない項目属性への割り当てが New コマンド内で検出された場合は、分析レポート内にエラーメッセージが表示され、プログラムの生成は行われません。
New コマンドは、Do while、
For Each コマンド、For to step など、ほかの繰り返し構造に含めることもできます。そうすることでバッチ挿入が可能になります (この場合、Blocking 節によりパフォーマンスが向上します)。複数のレコードを挿入するほかの方法として、複数の New コマンドを連続して実行することができます。New コマンドはネストすることもできます。
GeneXus は、New コマンドがあるたびに、レコードを挿入するテーブルを特定します。テーブルは、New コマンドの
BodyCode ブロック内 (When Duplicate 節ではない) の
割り当ての左側にある項目属性、および Defined by 節の項目属性 (存在する場合) に基づいて特定され、New コマンドの
ベーステーブルとして参照されます。GeneXus は、これらの項目属性すべてを含む
物理テーブルを検索します。テーブルが存在しない場合、プロシージャーの分析の後、問題に関するエラーメッセージがナビゲーションレポートに表示され、オブジェクトは生成されません。
必ずしもそうする必要はありません。New コマンドの
BodyCode 内でテーブルの項目属性が明示的に割り当てられていない場合、追加するレコードがどうなるかは、コンテキストによって異なります。
- 項目属性がインスタンス化されていない場合: 追加されるレコードの項目属性は、空 (または、対応する項目属性のプロパティによっては Null) になります。
- 項目属性がインスタンス化されている場合: 追加されるレコードの項目属性は、追加が行われた時点のコンテキストでのその項目属性の値となります。
コンテキストとはどのような意味なのでしょうか。
- 項目属性をパラメーターとして受け取る場合、その適用範囲はコード全体になります。指定されたり必要とされる場所で、その値を維持します。
- (New のような) コマンドが別のコマンド内にある場合 (つまり、後者のコマンドの適用範囲内にある場合)、後者のコマンド内で「インスタンス化」されたすべての項目属性が、前者の「コンテキスト」内にあることになります。たとえば、New コマンドが For Each コマンドの内側にある場合は、For Each コマンドの拡張テーブルのすべての項目属性が New コマンドのコンテキスト内にあることになります。これにはどのような意味があるでしょうか。たとえば、For Each コマンドで Customers テーブルを繰り返し処理していくつかの計算を行った後、コードに New コマンドが追加され、現在の顧客について、顧客の概要テーブルにレコードを挿入するとします。New コマンドに CustomerId 項目属性への明示的な割り当てがない場合、その値は For Each コマンド (のコンテキスト) から取得されます。
- New コマンドの BodyCode ブロックで指定されたコマンドは、そのレコードに対しては実行されません。
- 重複が検出された場合に実行するアクションは、When Duplicate コマンドを使用して指定できます。When Duplicate と Endnew の間にあるすべてのコマンドは、挿入時に重複キーが検出された場合に実行されます。
- GeneXus 変数: &ERR を作成できます。その場合、code = 1 に設定されます。
- GeneXus 変数: &ERRMSG を作成できます。その場合、メッセージに設定されます。
- 挿入するレコードが既に存在していて、そのレコードのデータを更新する必要がある場合、When Duplicate 節の中に For Each コマンドを指定する必要があります。
- Blocking 節の使用については、前出の「注」を参照してください。
Blocking 節が存在するかどうかで異なります。存在しない場合、挿入はコマンドの最後 (Endnew に達したとき) に行われます。存在する場合はブロックの最後に挿入が行われます。New コマンドにブロッキング因数 N があり、繰り返し構造 (For Each コマンドなど) の中にあるとします。For Each コマンドのボディ (およびその内部の New コマンド) を実行するたびに、New のレコードが実際に挿入されるわけではなく、サイズ N のメモリーブロック (バッファー) に追加されます。その後、バッファーがいっぱいになると、複数行の特殊な挿入がデータベースに送られ、ブロック全体が挿入されます。さらに、追加する N レコードの一部が重複していたことがわかった場合、特殊な挿入が失敗し、N ブロックを走査しながら、単純な挿入コマンドを使用して 1 件ずつ挿入が行われます。
New コマンド内で (
Call または
Udp を使用して) 別のプログラムを呼び出す場合、既にキーが存在していても、常に呼び出しが実行されます。
例
New
A = 1
B = 1
Calculation.call() //Call メソッドは省略できます。その場合、次のように記述します: Calculation()
When Duplicate
For each
B = 2
Endfor
EndNew
Calculation プロシージャーは、挿入するレコードのキーが既にテーブルに存在し、When Duplicate 節の前に呼び出し (call) が配置されている場合でも、常に呼び出されます。この動作は、Call コマンドが複数の値をフェッチして項目属性に割り当てることができるために発生します。
- 参照整合性は、更新中に自動的に確認はされません。
- 冗長性は、プロシージャーにおける挿入時に自動的に維持はされません。これは、プログラマーが行う必要があります。つまり、挿入するテーブルの項目属性に対して冗長性が定義されている場合、GeneXus で冗長項目属性にデータを格納するために、検索または計算が行われることはありません。式が冗長な場合その式は使用できず、値を明示的に計算して、関連する項目属性に割り当てる必要があります。
オブジェクト: Procedure オブジェクト
When duplicate 節
For each コマンドにおける Blocking 節
Updating with procedure-specific commands. Introduction