目的
IF、ELSEIF、ELSE、およびENDIFコマンドは、入力スクリプトの一部を条件付きで実行するために使用されます。IFコマンドは、THEN句を使用して単一命令(SI)の条件を作成するために単独で使用できます。または、THEN句なしでELSEIF、ELSE、およびENDIFコマンドと組み合わせて使用し、複数命令(MI)ブロックの条件を作成できます。MI IF構成はIFコマンドで始まり、ENDIFコマンドで終わることが最低限必要です。
IFおよびELSEIFコマンドを使用すると、明示的に指定された1つまたは複数の条件セットによって、テスト ステータス値を指定する必要があるかがチェックされます。これらの個別のチェックは、ANDまたはORを使用してまとめることや、NOT演算を介して無効にすることができます。総合的なテスト結果がTRUEであるかによって、命令の関連ブロックが実行されるかどうかが制御されます。
ELSEコマンドの暗黙的なテスト結果によって、関連する命令ブロックが実行されるかどうかが制御されます。
MI IF構成は、クローズされるためにそれぞれENDIFコマンドを必要とする、さまざまなレベルにネストすることができます。
対話型モード限定で、すべてのアクティブなMI IFレベルを直ちにクローズするために、ENDIFコマンドでALLオプションを使用することができます。
構文
構文規則:
- conditions
- ネストすることができる1つ以上の条件チェックです。各チェックの基本形式は、ステータス値の範囲内の整数と比較したステータス値キーワードです。すべてのステータス値キーワードを使用できます。詳細については、ステータス値のキーワードを参照してください。
- instruction
- 1つのSQLリクエストまたは1つ以上のBTEQコマンド。
使用上の注意
SI IFではなくMI IFを使用するには、IFコマンドでTHEN句を省略します。BTEQは、新しいMI IFレベルが開いたことを追跡し、IF条件の解析を開始して結果がTRUEかどうかを確認します。結果がTRUEの場合は、命令の関連するブロックが実行されます。条件がFALSEの場合、BTEQは代わりにそのブロックをバイパスして、ELSEIF、ELSE、またはENDIFコマンドを検索します。条件結果がTRUEのELSEIFが見つかった場合はそのブロックを実行し、結果がTRUEでない場合はバイパスします。ELSEIFでTRUEの条件が見つからず、ELSEを検出した場合には、ELSEの命令ブロックがTRUEのブロックであると見なされます。ENDIFを検出すると、BTEQは関連するMI IFレベルをクローズするため、他のFALSEブロックのバイパスが停止します。
TRUEのブロックを見つけると、BTEQはMI IFレベルの後続のELSEIFコマンドに関連する条件を解決しようとせず、代わりにレベルのすべてのELSEブロックと同様にこれらのブロックをバイパスします。
BTEQは、バッチ モードで検出される特定の構文エラーについて厳格です。例えば、どのMI IFレベルも開かれていない時点でELSEIF、ELSE、またはENDIFコマンドが検出されると、致命的なエラーが発生します。
ネストされるMI IFの最大数は利用可能な記憶容量に依存し、ハード制限は4294967294レベルです。
MI IFは、SQL ECHO文を使用して発行することができません。
SI IFは、THEN句が有効なBTEQコマンドを指定しており、このコマンドがSQL ECHO文を使用して発行することが有効である場合に限り、SQL ECHO文を使用して発行することができます。
- 直感的な設計の条件構成
- ネストされた条件パス
- 理解しやすいスクリプト
- 複数ブロックの構成でスクリプト化された命令が少ない
- 単一命令のブロックで条件結果が効率的に使用されている
- GOTOのジャンプでのみ必要なカスタムのラベル名規則
- 冗長度が低い出力オプションがある
GOTOは、MI IFと組み合わせて使用することができます。GOTOを使用すると、MI IF構成のネストされたすべてのレベルのブロック内にジャンプしたり、ブロック間をジャンプしたり、ブロック外にジャンプしたりすることができます。MI IF構成内でターゲットとなるラベルが見つかると、親レベルの親ブロックと同様に、それ以降は関連するブロックがそのレベルのTRUEブロックであると見なされます。
GOTOがアクティブな場合、ターゲットとなるLABELコマンドが見つかって実行されるまで、命令はスキップされます。どの命令がスキップされたかを反映した情報メッセージが生成されます。命令が実行されなかったMI IFブロックについても、同様の診断メッセージが生成されます。これらのメッセージにより、命令がバイパスされたことが示されます。
BRANCHMSGコマンドを使用して、分岐メッセージの出力形式が冗長ではなく簡潔になるように指定することができます。詳細についてはBRANCHMSGコマンドのセクションを参照してください。スクリプトが期待通りに問題なく動作することが確認されるまでは、冗長モードをオフにしないことを強く推奨します。
GOTOのスキップで検出されたすべてのLABELコマンドを確認する必要があります。ただし、GOTOがアクティブでない場合、MI IF内に存在するLABELコマンドはバイパスされます。
単一の命令は、1つのSQLリクエストのほか、1つの入力行または間にセミコロン、末尾にダッシュ文字を使用した複数の入力行で継続される1つまたは複数のBTEQコマンドで構成できます。単一の命令でいくつのBTEQコマンドを発行するかはユーザーに依存します。ただし、一部のBTEQコマンドでは、適切に機能するために独自の専用の命令が必要なため、常にユーザーの選択が可能なわけではありません。
予期しないスクリプトの実行結果につながる可能性があるため、IF SIのTHEN句では、すべての部分でMI IF構成を使用できません。BTEQではこれを検出する対策が取られますが、無効な構文をすべて検出することは不可能です。このため、すべてのMI IF構成の使用に関して、スクリプトが正しく作成されていることを確認する手順を踏んでから、実働環境でスクリプトを使用することを強く推奨します。
THEN句でMI IFが使用されて、MI IFで先頭のピリオドが欠落している場合に、誤認識のエラーが生じる解析シナリオが知られています。例:
.if activitycount=0 then if errorcode=99;
BTEQでは、最初にエラーを表示してネストされたMI IFを拒否する代わりに、欠落しているピリオド('.')についてのエラーを生成します。ピリオドが追加されると、BTEQは次の致命的なエラー メッセージを返します。
*** Error: Nesting a multi-instruction (MI) IF under a single-instruction (SI) IF..THEN is not allowed. If an MI IF was not intended, review and correct the syntax as needed to ensure successful THEN keyword parsing. Terminating the application.
BTEQでは、一度に1つのコマンドのみを解析して、直ちに実行するか、スキップするか、またはバイパスするかを判断します。このため、無効なMI IF構成のコマンド シーケンスに対して、BTEQが事前に対策を講じる代わりに、発生後に受動的に検出するだけのシナリオが生じる可能性があります。例えば、IFコマンドを検出した場合、BTEQはスクリプトの前方をチェックして必要なENDIFが欠落していないかを確認しません。またBTEQでは、ブロックのバイパスやGOTOのスキップ時に検出したMI IF、ELSEIF、ELSE、およびENDIFコマンドに対して、必要最低限の解析戦略をとる必要があります。これらのコマンドで指定された引数の確認を控えなければならないため、構文エラーに対して寛容にならざるを得なくなり、エラーが見落とされる可能性があります。BTEQがコマンドごとに通常の完全な構文妥当性検査を行なうのは、コマンドが"true"ブロックの一部として実際に実行されるときです。このためユーザーは、実働環境で使用する前に、責任を持ってMI IF構成のすべてのパスがチェック済みであることを確認する必要があります。
MI IF構成が開かれたことを検出するには、IFコマンドにTHEN句が含まれるかどうかをBTEQが判断できる必要があります。一部の無効な構文では、THENキーワードが検出されにくいために、BTEQが誤って新しいMI IFレベルを開始するよう決定する場合があります。このような構文違反は、予期しないコマンド実行パスにつながる可能性があります。BTEQでは、スクリプトの最後に到達するまで異常がまったく検出されないことがあります。強制された前提では、ENDIFが欠落しているかが判断されるだけです。このためユーザーには、実働環境で使用する前に条件ロジックを十分にチェックする責任があります。
BTEQではSQLトランザクションが検出されず、コマンドの構文エラーに基づいてトランザクションのロールバックをトリガーする手段もありません。このため、複数の命令を含むIF構成のスクリプトを使用する場合は、正確かどうかを十分にテストしてから実稼働環境で使用することが重要です。
例1 – 複数レベルのMI IF構成のためのフレームワーク コマンド
.IF ACTIVITYCOUNT = 1 <instructions> .IF ERRORCODE != 0 <instructions> .ELSEIF ( ( INSERTCOUNT = 1 ) AND ( UPDATECOUNT = 2 ) ) <instructions> .ELSE <instructions> .ENDIF .ELSEIF ACTIVITYCOUNT = 2 <instructions> .ELSE <instructions> .ENDIF
例2 – SI IFを使用した、データベース エラーのブランチ
直前のSQLリクエストで生成されたエラー コードが3000の場合に、NXTREPORTというラベルの付いたスクリプトに制御を渡すには、次のように入力します。
.IF ERRORCODE = 3000 THEN .GOTO NXTREPORT
例3 – SI IFを使用した、行が見つからないときのQUIT
SQLリクエストで行が見つからない場合に、戻りコードを1に設定するには、次のように入力します。
.IF ACTIVITYCOUNT = 0 THEN .QUIT 1
例4 – SQL ECHO文として出力されるSI IF
SQLマクロで使用する場合、このコマンドの形式は次のようになります。
ECHO '.IF ERRORCODE = 3000 THEN .REMARK ''Next'' ';
例5 - REPLACE PROCEDUREコンパイラ エラーの検出
自動化のために、ストアド プロシージャのREPLACEがデータベースによって正常に実行され、使用されているコンパイラがまだエラーを報告している場合に検出する必要がある場合があります。デフォルトでは、他で成功したコンパイルでエラーが発生したかどうかを判断する唯一の方法は、WARNINGCODEステータス値をチェックすることです。結果のERRORCODEが0になります。また、ACTIVITYCOUNT値は警告とエラーの合計総数になります。ただし、SQLストアド プロシージャ(SSP)の場合、5526警告コードを明示的にテストして、コンパイラがエラーを出したかどうかを確認できます。5527は警告のみを出していることを示します。ただし、コンパイラ自体がコンパイルを実行するために正しく構成されていない可能性もあります。これを検出するには、ERRORCODEステータス値をチェックする必要があります。単一の複数条件IFコマンドを使用すると、両方のテストを実行できます。次のIFコマンドは、COMPILEコマンドでいずれかのタイプのエラーが発生したかどうかを検出します。
.IF ((ERRORCODE!=0) OR (WARNINGCODE=5526)) THEN .GOTO errorpath
また、コンパイラの警告を検出することも目的の場合、WARNINGCODE値を0と比較する必要があります。
.IF ( NOT ((ERRORCODE=0) AND (WARNINGCODE=0)) ) THEN .GOTO errorpath
例6 – 欠落しているインポート ファイルの検出
インポート ファイルが欠落している、または空のシナリオをエラー ケースと考えるユーザーもいれば、そうではないと考えるユーザーもいます。これをエラーとして検出するための方法の一つは、最初に.OSまたは.TSOコマンドを使用して、ファイルの状態を検出できるシステム コールを発行してから、IFコマンドを使用してSYSTEMRETURNCODEステータス値をテストすることです。UNIX BTEQで使用される主な命令シーケンスは次のとおりです。
.OS test -e myfile.txt .IF SYSTEMRETURNCODE != 0 THEN .GOTO missingfile
PowerShellを使用するWindows BTEQの場合は、次のようになります。
.OS powershell "if ($false -eq (test-path -path myfile.txt)) {exit 1}" .IF SYSTEMRETURNCODE != 0 THEN .GOTO missingfile
例7 – 条件付きメッセージの出力
BTEQテストと分岐の一般的な用途の1つは、一定の条件に合致したときにメッセージを出力させることです。 例えば、作成したスクリプトに、データベースを変更することになっているリクエストが入っているとします。このリクエストの場合、エラー コードが返されなくても、アクティビティ カウントがゼロであれば問題が起きたことを示しています。それが操作上重大なリクエストであれば、スクリプト内のリクエストの直後に次のコマンドを入れることを試してみます。
.IF ACTIVITYCOUNT = 0 THEN .QUIT 65
この場合、事前定義された戻りコードである65の戻りコードは、そのリクエストによってデータベースは変更されなかったことを示します。
または次のようにして、まずスクリプト内の別の場所に分岐し、REMARKコマンドを使用して戻りコードを説明するメッセージが出力されるように指定し、それからBTEQを退去することを試してみます。
.IF ACTIVITYCOUNT = 0 THEN .GOTO PROB65 . . . .LOGOFF .EXIT 0 .LABEL PROB65 .REMARK 'Prob 65: The . . . request did not affect any rows' .QUIT 65