この章では埋込みSQLプログラムの動作を説明します。重要な用語の定義、基本概念の説明および主なルールを示します。
この章の構成は、次のとおりです。
この項では、後の各章で説明する内容の基本概念について説明します。
プリコンパイルを実行すると、通常どおりにコンパイルできるソース・ファイルが生成されます。プリコンパイルを行うと従来の開発過程より1ステップ処理が増えますが、これによって柔軟性に富んだアプリケーションを開発できるという大きな利点があります。
図2-1は、埋込みSQLアプリケーションの開発過程を示しています。
埋込みSQLという用語はアプリケーション・プログラム内に記述されているSQL文を指します。アプリケーション・プログラムは、その中にSQL文を含むのでホスト・プログラムと呼ばれます。また、アプリケーション・プログラムの記述に使用される言語はホスト言語と呼ばれます。たとえば、Pro*COBOLではCOBOLホスト・プログラムにSQL文を埋め込むことができます。
Oracleデータの操作および問合せには、INSERT文、UPDATE文、DELETE文およびSELECT文を使用します。INSERTはデータベース表へのデータ行の追加、UPDATEは行の変更、DELETEは不要な行の削除、SELECTは検索条件を満たす行の検索を行います。
アプリケーション・プログラムではSQL文のみ有効であり、SQL*Plus文は無効です。(SQL*Plusにはレポートの書式化、SQL文の編集、環境パラメータの設定のための文が追加されています。)
埋込みSQL文には、すべての対話型SQL文に加えて、Oracleとホスト・プログラムの間でデータを転送できるその他の文があります。埋込みSQL文には、実行文およびディレクティブという2つのタイプがあります。
実行SQL文は、データベースのコールを生成します。実行SQL文には、ほとんどすべての問合せ、データ操作言語(DML)文、データ定義言語(DDL)文、データ制御言語(DCL)文が含まれます。
一方、ディレクティブではSQLLIBのコールは発生せず、Oracleデータの操作も行われません。
ディレクティブはOracleオブジェクト、コミュニケーション領域およびSQL変数を宣言するために使用します。ディレクティブは、COBOLの宣言を記述できる位置であればどこでも記述できます。
付録E「埋込みSQL文およびプリコンパイラ・ディレクティブ」は、重要な文およびディレクティブを説明しています。表2-1に、いくつかの埋込みSQL文の一例を分類して示します。
表2-1 埋込みSQL文
ディレクティブ | |
---|---|
文 |
用途 |
ARRAYLEN* |
PL/SQLでのホスト表の使用 |
BEGIN DECLARE SECTION* END DECLARE SECTION* |
ホスト変数の宣言 |
DECLARE* |
Oracleオブジェクトの命名 |
INCLUDE* |
ファイルへのコピー |
VAR* |
変数の同値化 |
WHENEVER* |
ランタイム・エラーの処理 |
実行SQL文 |
|
文 |
用途 |
ALLOCATE* ALTER CONNECT* CREATE DROP GRANT NOAUDIT RENAME REVOKE TRUNCATE |
Oracleデータの定義および制御 |
CLOSE* DELETE EXPLAIN PLAN FETCH* INSERT LOCK TABLE OPEN* SELECT UPDATE |
Oracleデータの問合せおよび操作 |
COMMIT ROLLBACK SAVEPOINT SET TRANSACTION |
トランザクションの処理 |
DESCRIBE* EXECUTE* PREPARE* |
動的SQLの使用 |
ALTER SESSION SET ROLE |
セッションの制御 |
*対話形式はありません。 |
アプリケーション・プログラムでは、SQL文とホスト言語の文を自由に混在させることができ、SQL文でホスト言語の変数が使用できます。ホスト・プログラムにSQL文を記述するために特に必要なことは、SQL文をワードEXEC SQLで開始し、トークンEND-EXECで終了することのみです。Pro*COBOLが、実行EXEC SQL文をすべてランタイム・ライブラリSQLLIBのコールに変換します。
大部分の埋込みSQL文がそれに対応する対話型文と異なる点は、新しい句が追加されているか、プログラム変数が使用されていることのみです。次の対話型ROLLBACK文と埋込みROLLBACK文を比較してください。
ROLLBACK WORK; -- interactive * embedded EXEC SQL ROLLBACK WORK END-EXEC.
SQL文の後には、ピリオドやその他の終了記号を置くことができます。次は、どちらも正しいSQL文です。
EXEC SQL ... END-EXEC, EXEC SQL ... END-EXEC.
大部分のアプリケーション・プログラムは、静的SQL文および固定的なトランザクションを処理するように設計されています。この場合、処理を実行する前に各SQL文およびトランザクションの構成がわかります。つまり、発行されるSQLコマンド、変更されるデータベースの表、更新される列などが事前にわかります。第5章「埋込みSQL」を参照してください。
しかし、実行時に有効なSQL文を受け入れて処理する必要のあるアプリケーションもあります。この場合、関係するSQLコマンド、データベースの表および列は実行時までわからない場合もあります。
動的SQLは、プログラムの実行時にSQL文を受け取るかまたは作成し、データ型変換を明示的に管理する高度なプログラミング技術です。第9章「Oracle動的SQL」、第10章「ANSI動的SQL」および第11章「Oracle動的SQL: 方法4」を参照してください。
Pro*COBOLはPL/SQLブロックを1つの埋込みSQL文のように扱うため、SQL文の埋め込みが可能なアプリケーション・プログラム内の任意の場所にPL/SQLブロックを埋め込むことができます。PL/SQLをホスト・プログラム内に埋め込むには、PL/SQLと共有する変数を宣言し、キーワードEXEC SQL EXECUTEおよびEND-EXECを使用してPL/SQLブロックを囲みます。
PL/SQLはすべてのSQLデータ操作コマンドおよびトランザクション処理コマンドをサポートしているため、埋込みPL/SQLブロックからOracleデータを柔軟かつ安全に操作できます。PL/SQLの詳細は、第6章「埋込みPL/SQL」を参照してください。
ホスト変数とは、COBOL言語で宣言され、Oracleとの間で共有される(つまり、ユーザー・プログラムおよびOracleの両方がその値を参照できる)スカラー変数または表変数、あるいはグループ項目です。ホスト変数はOracleとプログラムの間の通信を仲介します。
データベースにデータを渡すには入力ホスト変数を使用します。データベースからプログラムにデータおよびステータス情報を渡すには、出力ホスト変数を使用します。
ホスト変数は、式を使用できる位置であればどこに使用してもかまいません。SQL文では、ホスト変数にコロン(:)の接頭辞を付けて、データベース・スキーマ名からホスト変数を切り分ける必要があります。
任意のホスト変数に任意指定の標識変数を関連付けることができます。標識変数とは、ホスト変数の値または条件を示す整変数です。NULLとは、値がないか、未知であるか、または適用不可能な値です。標識変数を使用すると、入力ホスト変数にNULLを割り当てたり、出力変数のNULLまたは出力文字ホスト変数の切り捨てられた値を検出できます。
ホスト変数についての注意事項は、次のとおりです。
COBOL文では、先頭にコロンを付けない。
ALTERやCREATEなどのデータ定義(DDL)文で使用しない。
SQL文中に標識変数を記述する場合は、前にコロンを付けて、関連付けられたホスト変数の直後に記述してください(標識変数の前にオプションのキーワードINDICATORを付けることも可能です)。
SQL文で使用するプログラム変数はすべて、COBOL言語の規則に従って宣言する必要があります。この場合、通常のスコープ規則が適用されます。COBOLでは変数名の長さは任意ですが、Pro*COBOLでは最初の30文字のみが有効になります。数字で始まるものも含め、有効なCOBOL識別子であればどれでもホスト変数識別子として使用できます。
ホスト変数の外部データ型およびそのソース・データベースまたはターゲット・データベース列の内部データ型は、同じである必要はありませんが、互換性が必要です。表4-9「内部データ型と外部データ型の間での変換」は、必要に応じてOracle9iによって自動的に変換される、互換性のあるデータ型を示しています。
一般的に、ホスト・プログラムはデータベースにデータを入力し、データベースはホスト・プログラムにデータを出力します。Oracleは、入力データをデータベースの表に挿入し、出力データを選択して プログラム・ホスト変数に格納します。データ項目を格納するために、Oracleはそのデータ型を認識する必要があります。データ型によって、記憶形式および値のスコープが指定されます。
Oracleは、内部データ型および外部データ型の2種類のデータ型を認識します。内部データ型はOracleがデータベース列にどのようにデータを格納するかを指定します。また、Oracleではデータベース疑似列を表すときに内部データ型を使用します。これは、特定のデータ項目を戻しますが、表の中に実際の列はありません。
外部データ型は、データがホスト変数にどのように格納されるかを指定します。ホスト・プログラムからOracleにデータが入力されると、Oracleは必要に応じて、入力ホスト変数の外部データ型とデータベース列の内部データ型の変換を行います。また、Oracleからホスト・プログラムにデータを出力するときも、Oracleは必要に応じて、データベース列の内部データ型と出力ホスト変数の外部データ型の変換を行います。
注意: 動的SQL方法4またはデータ型の同値化を使用すると、デフォルトのデータ型変換をオーバーライドできます。データ型の同値化の詳細は、「DATE文字列フォーマットの明示的な制御」を参照してください。 |
Pro*COBOLでは、表ホスト変数(ホスト表と呼ばれます)を定義して、それを単一のSQL文で操作できます。SELECT文、FETCH文、DELETE文、INSERT文およびUPDATE文を使用すると、大量のデータの問合せおよび操作を簡単に行えます。
ホスト表の詳細は、第7章「ホスト表」を参照してください。
埋込みSQL文を実行すると、エラーまたは警告が発生する場合があります。これらの結果を処理する方法が必要です。Pro*COBOLは、次のエラー処理方法を備えています。
SQLCODE状態変数
SQLSTATE状態変数
SQLコミュニケーション領域(SQLCA)
WHENEVER文
Oracle通信領域(ORACA)
SQL文の実行後、OracleサーバーはSQLCODEまたはSQLSTATEという変数にステータス・コードを戻します。ステータス・コードは、そのSQL文の実行に成功したか、エラーまたは警告状態が発生したかを示します。
Oracleは、実行時のステータス情報をプログラムに渡すためにプログラム変数を使用します。SQLCAは、このプログラム変数を定義するデータ構造です。SQLCAを使用すると、直前に実行を試みた作業に関するOracleからのフィードバックに基づいて、別の処理を行うことができます。たとえば、DELETE文が成功したかどうかを調べ、成功した場合には、削除された行数を調べることができます。
SQLCAによって、診断チェックおよびイベント処理ができます。実行時には、Oracle9iからプログラムに渡されるステータス情報をSQLCAで保持します。SQL文の実行後、Oracle8iにより図2-2に示すようにSQLCA変数が設定されて、結果が示されます。
INSERT文、UPDATE文またはDELETE文が成功したかどうかをチェックできます。成功した場合は、実行された行数を調べることができます。また、文が失敗した場合には、何が原因かを詳しく調べることができます。
MODE={ANSI13 | ORACLE}のとき、SQLCAを宣言するには、SQLCAをハードコーディングするか、INCLUDE文を使用してプログラムにコピーする必要があります。SQLCAの宣言および使用方法は、「SQLコミュニケーション領域の使用」を参照してください。
WHENEVER文を使用すると、Oracleがエラーまたは警告状態を検出した際に自動的に行われるアクションを指定できます。アクションには、次の文から続行、サブプログラムのコール、ラベル付きの命令への分岐、段落の実行、停止などがあります。
ランタイム・エラーについて、SQLCAに格納されている情報よりも詳細な情報が必要なときにORACAを使用します。ORACAは、Oracleの通信を扱うデータ構造です。この中にはカーソル統計情報、現行のSQL文に関する情報、オプションの設定、およびシステムの統計情報が含まれます。
Oracleは、SQL文が成功したか失敗したかについて、状態変数SQLSTATEおよびSQLCODEで戻します。プリコンパイラ・オプションMODE=ORACLEのときは、SQLCAを組み込むことによってSQLCODEを宣言できます。MODE=ANSIの場合はSQLSTATEまたはSQLCODEを宣言する必要がありますが、SQLCAの宣言は不要です。
詳細は、第8章「エラー処理および診断」を参照してください。
この項では、埋込みSQLの構文、コーディング規則、Pro*COBOL固有の機能および制限事項を説明します。
Pro*COBOLプリコンパイラのオプションと値、EXEC SQL文、インライン・コマンドおよびCOBOL文には大文字と小文字の区別がありません。Pro*COBOLプリコンパイラは大文字のトークンも小文字のトークンも受け入れます。
Pro*COBOLでは、使用しているオペレーティング・システムに標準のCOBOL(通常はCOBOL-85またはCOBOL-74)がサポートされます。両方のCOBOLをサポートするプラットフォームもあります。詳細は、使用しているシステム固有のOracleマニュアルを参照してください。
プリコンパイラ・オプションFORMATは、ソース・コードの書式を指定します。FORMAT=ANSI(デフォルト)と指定すると、ANSI規格にできるかぎり準拠したコードを作成できます。ANSI規格では、1から6桁目にオプションの順序番号を、7桁目(インジケータ領域)にはコメント行または継続行を記述できます。
分割ヘッダー、セクション・ヘッダー、段落の名前、FDおよび01文は、8から11桁目(A領域)から始まります。EXEC SQL文、EXEC ORACLE文など、その他の文は、領域B(12から72桁)に記述する必要があります。ソース・コード書式のガイドラインは、コンパイラの規則によって変更できます。
FORMAT=TERMINALを指定すると、COBOL文を1桁目(一番左の桁)から始めるか、または1桁目をインジケータ領域にできます。この書式も、コンパイラの規則によって変更されます。
FORMAT=VARIABLEを指定すると、B領域の長さの柔軟性が許可されます。
COBOL文の書式が実際に受け付けられるかどうかを判断するには、使用しているプラットフォーム用のCOBOLコンパイラのマニュアルを参照してください。
SQLでは、次の例に示すように、カンマを使用してリスト項目を区切る必要があります。
EXEC SQL SELECT ENAME, JOB, SAL INTO :EMP-NAME, :JOB-TITLE, :SALARY FROM EMP WHERE EMPNO = :EMP-NUMBER END-EXEC.
COBOLでは、カンマまたは空白を使用してリスト項目を区切ることができます。たとえば、次の2つの文は等価です。
ADD AMT1, AMT2, AMT3 TO TOTAL-AMT. ADD AMT1 AMT2 AMT3 TO TOTAL-AMT.
SQL文の中にCOBOLのコメント行を入れることができます。COBOLのコメント行は、インジケータ領域内で先頭にアスタリスク(*)を付けて始めます。
SQL文の中には、「- -」で始まるANSI SQLスタイルのコメントを行の最後に記述できます(ただし、SQL文の最終行の後には記述できません)。
行の残りの部分には、「*>」の2文字で始まるCOBOLコメントを記述できます。
SQL文には、C言語スタイル(/* ... */)のコメント文が記述できます。
次の例には、前述の4つのスタイルのコメントがすべて含まれています。
MOVE 12 TO DEPT-NUMBER. *> This is the software development group. EXEC SQL SELECT ENAME, SAL * assign column values to output host variables INTO :EMP-NAME, :SALARY -- output host variables /* column values assigned to output host variables */ FROM EMP WHERE DEPTNO = :DEPT-NUMBER END-EXEC. -- illegal Comment
コメントをネストしたり、SQL文の最終行の終了記号END-EXECの後にコメントを入れることはできません。
次の例に示すように、COBOLの規則に従ってSQL文を次の行へ続けることができます。
EXEC SQL SELECT ENAME, SAL INTO :EMP-NAME, :SALARY FROM EMP WHERE DEPTNO = :DEPT-NUMBER END-EXEC.
継続インジケータは必要ありません。
ある行から次の行に文字列リテラルを継続するには、72桁までリテラルを記述します。次の行の7桁目にハイフン(-)、12桁以降に二重引用符を記述して、残りのリテラルを記述します。次に、例を示します。
WORKING STORAGE SECTION. ... EXEC SQL BEGIN DECLARE SECTION END-EXEC. ... 01 UPDATE-STATEMENT PIC X(80) VALUE "UPDATE EMP SET BON - "US = 500 WHERE DEPTNO = 20". EXEC SQL END DECLARE SECTION END-EXEC.
Copy文は、Pro*COBOLでは解析されません。したがって、COPYコマンドが含まれているファイルには、ホスト変数の定義や埋込みSQL文を含めないでください。かわりに、INCLUDEプリコンパイラ文を使用します。詳細は、「INCLUDE文の使用」を参照してください。INCLUDEおよびDECLARE_SECTION=YESを使用する場合は注意が必要です。グループ項目は、宣言部の中または外のどちらかにすべてを記述する必要があります。
Pro*COBOLでは、ENVIRONMENT DIVISIONでのDECIMAL-POINT IS COMMA句がサポートされます。ソース・ファイルにDECIMAL-POINT IS COMMA句が指定されていると、VALUE句内で数値リテラルの小数部分の開始記号としてカンマを使用できます。
たとえば、次の句は有効です。
IDENTIFICATION DIVISION. PROGRAM-ID. FOO ENVIRONMENT DIVISION. CONFIGURATION SECTION. SPECIAL-NAMES. DECIMAL-POINT IS COMMA. *> <-- ** DATA DIVISION. WORKING-STORAGE SECTION. ... 01 WDATA1 PIC S9V999 VALUE +,567. *> <--- ** 01 WDATA2 PIC S9V999 VALUE -,234. *> <--- ** ...
COBOLの文字列定数およびリテラルのデリミタの指定には、LITDELIMオプションを使用します。LITDELIM=APOSTと指定すると、Pro*COBOLではCOBOLコードを生成する際に引用符を使用します。LITDELIM=QUOTE(デフォルト)と指定すると、次に示すように二重引用符を使用します。
CALL "SQLROL" USING SQL-TMP0.
SQL文では、次の例に示すように、特殊文字または小文字を含んでいる識別子は二重引用符で区切る必要があります。
EXEC SQL CREATE TABLE "Emp2" END-EXEC.
また、文字列定数を区切る場合は、次の例のように引用符を使用します。
EXEC SQL SELECT ENAME FROM EMP WHERE JOB = 'CLERK' END-EXEC.
Pro*COBOLは、Pro*COBOLソース・ファイルで使用されているデリミタに関係なく、LITDELIMの値で指定されたデリミタを生成します。
次の分割ヘッダーはオプションです。
IDENTIFICATION DIVISION
ENVIRONMENT DIVISION
DATA DIVISION
PROCEDURE DIVISIONヘッダーはオプションではありません。プリコンパイルできるソースは次のとおりです。
*IDENTIFICATION DIVISION header is optional PROGRAM-ID. HELLO. *ENVIRONMENT DIVISION header is optional CONFIGURATION SECTION. *DATA DIVISION header is optional WORKING-STORAGE SECTION. PROCEDURE DIVISION. DISPLAY "Hello World!". STOP RUN.
Pro*COBOLプログラムでSQL文を使用する場合は、SQL文の前にEXEC SQLを指定し、SQL文の最後にEND-EXECキーワードを指定します。埋込みSQL構文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
HIGH-VALUE、ZEROおよびSPACEなどの表意定数は、SQL文では使用できません。たとえば、次のSQL文は無効です。
EXEC SQL DELETE FROM EMP WHERE COMM = ZERO END-EXEC.
このかわりに、次のように指定します。
EXEC SQL DELETE FROM EMP WHERE COMM = 0 END-EXEC.
Pro*COBOLが処理できるソース・ファイルの長さには制限があります。内部で使用する変数によって、生成されるファイルのサイズが制限される場合があります。許容される行数の絶対的な制限はありませんが、次に示すようなソース・ファイルの状態によって、ファイル・サイズに制約が生じます。
埋込みSQL文の複雑さ(たとえば、バインド変数および定義変数の数)
データベース名の使用の有無(たとえば、AT句を使用してデータベース名に接続する場合)
埋込みSQL文の数
この制限に関連した問題を防ぐには、複数のプログラム単位を使用してソース・ファイルのサイズを小さくします。
ホスト変数の宣言でワードFILLERを使用できます。ワードFILLERは、明示的に参照できないグループの基本項目を指定するときに使用します。次の宣言は有効です。
01 STOCK. 05 DIVIDEND PIC X(5). 05 FILLER PIC X. 05 PRICE PIC X(6).
ホスト変数には、有効な標準COBOL識別子であればどれでも使用できます。変数名の長さに制限はありませんが、最初の30文字のみ有効になります。COBOLコンパイラが認識する有効文字の最大数は30です。
SQL92規格準拠には、ホスト変数名の長さを18文字以下に制限します。
アプリケーションで使用制限があるワードの一覧は、付録B「予約語、キーワードおよびネームスペース」を参照してください。
静的SQL文ではハイフン付きのホスト変数名を使用できますが、動的SQLでは使用できません。たとえば、次の指定は無効です。
MOVE "DELETE FROM EMP WHERE EMPNO = :EMP-NUMBER" TO SQLSTMT. EXEC SQL PREPARE STMT1 FROM SQLSTMT END-EXEC.
ホスト変数を宣言する際、レベル番号01から49および77を使用できます。Pro*COBOLでは、VARYING句を含む変数またはレベル49または77として宣言する擬似型の変数(先頭に「SQL-」が付くデータ型の変数)は使用できません。
MAXLITERALオプションを使用して、Pro*COBOLで生成される文字列リテラルの最大長を指定して、コンパイラ制限を超えないようにします。Pro*COBOLの場合はデフォルト値は256ですが、これより小さい値の指定が必要な場合もあります。
マルチバイト・キャラクタ・データを扱うために、ANSI規格の各国語キャラクタ・セットのデータ型がサポートされています。使用しているコンパイラでPIC N句またはPIC G句がサポートされている場合は、これらの句によって固定長のNCHAR文字列を格納する変数が定義されます。可変長のマルチバイト各国語キャラクタ・セット文字列を格納するには、長さフィールドおよび文字列フィールドから構成されるCOBOLグループ項目を使用します。「VARCHAR変数」を参照してください。
クライアント側のグローバリゼーション・サポート各国語キャラクタ・セットを指定するために環境変数NLS_NCHARを使用できます。
SQLでは、NULLは欠落した列値、不明な列値または適用できない列値を表し、0(ゼロ)とも空白とも等価ではありません。NULLをNULLでない値に変換するにはNVL関数を使用し、NULLを検索するにはIS [NOT] NULL比較演算子を使用します。また、NULLの挿入およびテストを行うときは標識変数を使用します。
次の例に示すように、COBOLの標準的な段落の名前およびセクションの名前をSQL文と関連付けできます。
LOAD-DATA. EXEC SQL INSERT INTO EMP (EMPNO, ENAME, DEPTNO) VALUES (:EMP-NUMBER, :EMP-NAME, :DEPT-NUMBER) END-EXEC.
また、次の例のようにWHENEVER ... DOまたはWHENEVER ... GOTOで段落の名前を参照することもできます。
PROCEDURE DIVISION. MAIN. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. ... SQL-ERROR SECTION. ...
COBOLのREDEFINES句を使用して、グループ項目または基本項目を再定義できます。たとえば、次の宣言は有効です。
EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 REC-ID PIC X(4). 01 REC-NUM REDEFINES REC-ID PIC S9(4) COMP. EXEC SQL END DECLARE SECTION END-EXEC.
EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 STOCK. 05 DIVIDEND PIC X(5). 05 PRICE PIC X(6). 01 BOND REDEFINES STOCK. 05 COUPON-RATE PIC X(4). 05 PRICE PIC X(7). EXEC SQL END DECLARE SECTION END-EXEC.
1つのINTO句で、グループ項目ホスト変数およびその再定義の両方の項目が使用されていても、Pro*COBOLは警告もエラーも発行しません。
COBOLの文はCOBOL文またはSQL文、あるいはその両方を1つ以上含み、ピリオドで終わります。次の例に示すように、条件文では最後の文のみピリオドで終わる必要があります。
IF EMP-NUMBER = ZERO MOVE FALSE TO VALID-DATA PERFORM GET-EMP-NUM UNTIL VALID-DATA = TRUE ELSE EXEC SQL DELETE FROM EMP WHERE EMPNO = :EMP-NUMBER END-EXEC ADD 1 TO DELETE-TOTAL. END-IF.
SQL文は、カンマ、ピリオドまたはその他のCOBOL文で終了できます。
データベース・サーバーとアプリケーション・プログラムの間のデータの受渡しには、ホスト変数とエラー処理が必要です。この項では、これらの必要条件を満たす方法を説明します。
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
次の文で終了します。
EXEC SQL END DECLARE SECTION END-EXEC.
ホスト変数および標識変数の宣言
ホスト変数以外のCOBOL変数
EXEC SQL DECLARE文
EXEC SQL INCLUDE文
EXEC SQL VAR文
EXEC ORACLE文
COBOLコメント
プログラムで使用する4つのホスト変数を宣言した例を次に示します。
WORKING-STORAGE SECTION. ... EXEC SQL BEGIN DECLARE SECTION END-EXEC. ... 01 EMP-NUMBER PIC 9(4) COMP VALUE ZERO. 01 EMP-NAME PIC X(10) VARYING. 01 SALARY PIC S9(5)V99 COMP-3 VALUE ZERO. 01 COMMISSION PIC S9(5)V99 COMP-3 VALUE ZERO. EXEC SQL END DECLARE SECTION END-EXEC.
宣言部はオプションです。Pro*COBOLには、リリース8.0以前のリリースとの下位互換性を保つために、宣言部内の宣言のみホスト変数として使用するかどうかを明示的に制御できるコマンドライン・プリコンパイラ・オプションが用意されています。このオプションは次のとおりです。
DECLARE_SECTION={YES | NO}(デフォルトはNO)
DECLARE_SECTIONオプションは、コマンドラインまたは構成ファイル内で指定する必要があります。
MODE=ORACLEおよびDECLARE_SECTION=YESと設定した場合は、宣言部の中で宣言した変数のみホスト変数として使用できます。MODE=ANSIと設定すると、DECLARE_SECTIONは暗黙的にYESに設定されます。マクロ・オプションおよびマイクロ・オプションの詳細は、「マクロ・オプションおよびマイクロ・オプション」を参照してください。
DECLARE_SECTIONをYESに設定した場合は、SQL文中で使用するすべてのプログラム変数を宣言部内で宣言する必要があります。DECLARE_SECTIONをNOに設定した場合は、宣言部を使用するかどうかを選択できます。この場合、ホスト変数および標識変数は宣言部の中でも宣言部の外でも宣言できます。このようなオプションとしての使用は、リリース8.0以下のリリースと異なる点です。オプションの詳細は、「DECLARE_SECTION」を参照してください。
1つのプリコンパイル・ユニットで複数の宣言部を使用できます。さらに、複数の独立したプリコンパイル・ユニットを1つのホスト・プログラムに含めることもできます。
INCLUDE文を使用して、ホスト・プログラムにファイルをコピーできます。次に例を示します。
* Copy in the SQL Communications Area (SQLCA) EXEC SQL INCLUDE SQLCA END-EXEC. * Copy in the Oracle Communications Area (ORACA) EXEC SQL INCLUDE ORACA END-EXEC.
INCLUDEは、どのファイルに対しても実行できます。Pro*COBOLプログラムをプリコンパイルすると、EXEC SQL INCLUDE文はそれぞれ、その文で指定されたファイルのコピーに置き換えられます。
システムでファイル拡張子が使用される場合にファイル拡張子の指定を省略すると、Pro*COBOLではソース・ファイルのデフォルトの拡張子(通常はCOB)が使用されます。詳細は、使用しているシステム固有のOracleマニュアルを参照してください。
システムでディレクトリが使用される場合は、次のようにINCLUDEオプションを使用して、INCLUDEするファイルの検索パスを設定できます。
INCLUDE=path
このとき、pathのデフォルト値はカレント・ディレクトリです。
Pro*COBOLは、最初にカレント・ディレクトリを検索し、次にINCLUDEオプションで指定されたディレクトリを検索して、最後に標準INCLUDEファイル用のディレクトリを検索します。このため、SQLCAやORACAなどの標準ファイルのパスを指定する必要はありません。標準以外のファイルについては、カレント・ディレクトリに格納されている場合を除いてパスが必要です。
また次のように、コマンドラインで複数のパスを指定することもできます。
... INCLUDE=<path1> INCLUDE=<path2> ...
複数のパスを指定すると、カレント・ディレクトリ、path1ディレクトリ、path2ディレクトリの順に検索されます。標準INCLUDEファイルを含むディレクトリは最後に検索されます。パスの構文はシステムによって異なります。詳細は、使用しているシステム固有のOracleマニュアルを参照してください。
Pro*COBOLでは、検索パスの指定があっても、カレント・ディレクトリでファイルが先に検索されることに注意してください。INCLUDEするファイルが別のディレクトリにある場合は、カレント・ディレクトリに同じ名前のファイルがないことを確認してください。また、検索パスでそのディレクトリより前にあるディレクトリにも同じ名前のファイルがないことを確認してください。大/小文字が区別されるオペレーティング・システムを使用している場合は、ファイルを格納したときと同じように大/小文字を区別してファイル名を指定してください。
COBOLにおけるプログラムのネストとは、あるプログラムを別のプログラムの中に入れることを意味します。中に含まれるプログラムは、それを含んでいるプログラムのリソースの一部を参照できます。また、ネストされたプログラムと上位のプログラムの中で同じ名前を使用できます。名前はそれぞれのプログラムの中でのみ認識されるため、異なるデータ項目の記述に同じ名前を使用しても競合することはありません。ただし、上位プログラムの構成部に記述されている名前は、ネストされたプログラムから参照できます。
一部のコンパイラはGLOBAL句をサポートしていません。Pro*COBOLではネストされたプログラムがサポートされるので、生成されたコードにはGLOBAL句が含まれます。GLOBAL句が無条件に生成されるのを避けるには、プリコンパイル・オプションのNESTED=NOを指定してください。NESTED(=YESまたはNO)は、デフォルトでYESに設定されています。構成ファイルまたはコマンドラインで使用できますが、インライン(EXEC ORACLE文)では使用できません。
関連項目: 「NESTED」を参照してください。
プログラムでは、ネストされたプログラムを複数記述できます。同様に、ネストされたプログラムについても、その中にさらにネストされたプログラムを記述できます。ネストされたプログラムは、それを含んでいるプログラムのEND PROGRAMヘッダーの直前に記述する必要があります。
ネストされたプログラムをコールできるのは、そのプログラムを直接的または間接的に含んでいるプログラムのみです。ネストされたプログラムを別のプログラム(ネストのツリー構造の別の分岐にあるプログラムも含む)からコールする場合は、ネストされたプログラムのPROGRAM-ID段落にCOMMON句を記述します。COMMONは、ネストされたプログラムでのみ使用できます。
PROGRAM-ID. <nested-program-name> COMMON.
ファイル定義にGLOBAL句を使用して、レベル01のデータ項目(自動的にグローバルになる従属項目)を記述できます。このように記述したデータ項目は、それらのデータ項目に直接的または間接的に含まれるすべてのサブプログラムで参照できます。上位プログラムにはGLOBALを使用します。上位プログラムでGLOBALと宣言された名前と同じ名前がネストされたプログラムで定義されていると、COBOLではネストされたプログラムの中の宣言が使用されます。データ項目にREDEFINES句が使用されているときは、GLOBALはREDEFINESの後に記述する必要があります。
FD file-name GLOBAL ... 01 data-name1 GLOBAL ... 01 data-name2 REDEFINES data-name3 GLOBAL ...
Pro*COBOLでは、1つのソース・ファイル内に埋込みSQLを持つ複数のネストされたプログラムを格納できます。上位プログラムでグローバルとしてマークされた、上位プログラム・レベルで有効なホスト変数である01レベルの項目はすべて、上位プログラムが直接的または間接的に含んでいるすべてのプログラムで、有効なホスト変数として使用できます。次の例を考えてみます。
IDENTIFICATION DIVISION. PROGRAM-ID. MAINPROG. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 REC1 GLOBAL. 05 VAR1 PIC X(10). 05 VAR2 PIC X(10). 01 VAR1 PIC X(10) GLOBAL. EXEC SQL END DECLARE SECTION END-EXEC. PROCEDURE DIVISION. ... <main program statements> ... IDENTIFICATION DIVISION. PROGRAM-ID. NESTEDPROG. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 VAR1 PIC S9(4). PROCEDURE DIVISION. ... EXEC SQL SELECT X, Y INTO :REC1 FROM ... END-EXEC. EXEC SQL SELECT X INTO :VAR1 FROM ... END-EXEC. EXEC SQL SELECT X INTO :REC1.VAR1 FROM ... END-EXEC. ... END PROGRAM NESTEDPROG. END PROGRAM MAINPROG.
メイン・プログラムでホスト変数REC1がグローバルとして宣言されているため、ネストされたプログラムは最初のSELECT文でREC1を使用できます(REC1を宣言する必要はありません)。VAR1は、メイン・プログラムではグローバル変数として宣言され、ネストされたプログラムではローカル変数として宣言されています。このため、2番目のSELECT文ではS9(4)として宣言されたVAR1が使用され、グローバル宣言は無効になります。3番目のSELECT文では、PIC X(10)として宣言された、REC1のグローバルなVAR1が使用されます。
前述の例は、DECLARE_SECTION=NOが使用されている場合の結果を説明しています。DECLARE_SECTION=YESの場合、Pro*COBOLは、宣言部の中で宣言されていないかぎりホスト変数を認識しません。DECLARE_SECTION=YESと指定して前述のプログラムをプリコンパイルすると、2番目のSELECT文の結果、あいまいなホスト変数エラーが発生します。最初のSELECT文および3番目のSELECT文は、DECLARE_SECTION=NOの場合と同じです。
注意: 再帰的なネストされたプログラムは、サポートされていません。
ネストされたプログラムでは、提供される組込みSQLCA(「SQLCA状態変数」を参照)の定義はグローバルとして宣言されるため、SQLCAの宣言は上位プログラム内でのみ必要になります。SQLCAは、新しいSQL文が実行されるたびに変更できます。提供されるSQLCAはいつでも変更できるため、ネストされたプログラムで追加のSQLCA領域を宣言する場合にはグローバル指定を削除できます。これはSQLDAおよびORACAにも適用されます。
条件付きプリコンパイルとは、特定の条件に基づいてコード・セクションをホスト・プログラムに組み込む(または除外する)プリコンパイルの方法です。たとえば、UNIXでプリコンパイルするときにはあるコード・セクションを組み込み、VMSでプリコンパイルするときには別のコード・セクションを組み込むことができます。条件付きプリコンパイルの使用により、様々な環境で実行できるプログラムを作成できます。
環境および処理を定義する文によってコードの条件文が区切られます。コード・セクションには、ホスト言語の文を記述することも、EXEC SQL文を記述することもできます。次の文でプリコンパイルの条件を制御します。
* -- define a symbol EXEC ORACLE DEFINE symbol END-EXEC. * -- if symbol is defined EXEC ORACLE IFDEF symbol END-EXEC. * -- if symbol is not defined EXEC ORACLE IFNDEF symbol END-EXEC. * -- otherwise EXEC ORACLE ELSE END-EXEC. * -- end this control block EXEC ORACLE ENDIF END-EXEC.
条件文はEND-EXEC
で終了する必要があります。
注意: 使用しているコンパイラの条件付きコンパイル機能が、Pro*COBOLでサポートされない場合があります。 |
次の例では、シンボルSITE2が定義されているときのみSELECT文がプリコンパイルされます。
EXEC ORACLE IFDEF SITE2 END-EXEC. EXEC SQL SELECT DNAME INTO :DEPT-NAME FROM DEPT WHERE DEPTNO = :DEPT-NUMBER EXEC ORACLE ENDIF END-EXEC.
次の例に示すように条件ブロックはネストできます。
EXEC ORACLE IFDEF OUTER END-EXEC. EXEC ORACLE IFDEF INNER END-EXEC. ... EXEC ORACLE ENDIF END-EXEC. EXEC ORACLE ENDIF END-EXEC.
ホスト言語または埋込みSQLのコードをIFDEFとENDIFの間に記述し、シンボルを定義しないことによって、そのコードをコメントとして扱えます。
シンボルを定義するには2通りの方法があります。1つは、次の文をホスト・プログラムに組み込む方法です。
EXEC ORACLE DEFINE symbol END-EXEC.
もう1つは、次の構文を使用してコマンドラインでシンボルを定義する方法です。
... INAME=filename ... DEFINE=symbol
symbolの部分は大/小文字区別がありません。
Pro*COBOLをシステムにインストールした時点で、ポート固有のいくつかのシンボルが事前定義されています。たとえば、オペレーティング・システムの事前定義済シンボルには、CMS、MVS、UNIXおよびVMSがあります。
複数のCOBOLプログラム・モジュールを別々にプリコンパイルし、後でリンクして1つの実行可能プログラムを作成できます。これにより、プログラムの機能コンポーネントの作成とデバッグを複数のプログラマが分担して行う場合に必要とされる、モジュラー・プログラミングが可能になります。個々のプログラム・モジュールを同じ言語で作成する必要はありません。
カーソル名はSQL識別子であり、そのスコープはプリコンパイル・ユニットです。このためカーソル操作が複数のプリコンパイル・ユニット(ファイル)に及ぶことはありません。つまり、あるファイルで宣言したカーソルは、別のファイルでオープンまたはフェッチできません。したがって、分割プリコンパイルを実行するときは、指定のカーソルに対する定義および参照がすべて1つのファイル内に記述されていることを確認してください。
Oracleに接続するプログラム・モジュールをプリコンパイルするときは、MAXOPENCURSORSに、どのプログラム・モジュールについても十分な大きさの値を指定してください。指定したMAXOPENCURSORSの値は、別のプログラム・モジュールに使用すると無視されます。実行時には、その接続に有効な値のみ使用されます。
実行可能プログラムを作成するには、Pro*COBOLによって生成されたソース・ファイルをコンパイルし、その結果得られたオブジェクト・モジュールを、SQLLIBおよびシステム固有のOracleライブラリ内の必要なモジュールとリンクさせる必要があります。
リンカーはオブジェクト・モジュール内のシンボリック参照を解決します。これらの参照で競合が発生すると、リンクは失敗します。プリコンパイル済のプログラムにサード・パーティのソフトウェアをリンクするときに、このような競合が起こる可能性があります。こうした問題が生じるのは、サード・パーティのソフトウェアの中には Oracleと互換性のないものがあるためです。Oracleサポート・サービスに問い合せて、使用するソフトウェアがサポートされているかどうかを確認してください。
コンパイルおよびリンクの方法はシステムによって異なります。たとえば、システムによっては、ホスト言語プログラムをコンパイルするときにコンパイラの最適化をオフにする必要があります。手順は、使用しているシステム固有のOracleマニュアルを参照してください。
このマニュアルで紹介するほとんどのプログラム例では、DEPTおよびEMPという 2つのサンプル・データベース表が使用されています。デモ・ディレクトリにこの2つの表が含まれていない場合は、サンプル・プログラムを実行する前に表を作成してください。次に示すのはそれぞれの表の定義です。
CREATE TABLE DEPT (DEPTNO NUMBER(2), DNAME VARCHAR2(14), LOC VARCHAR2(13)); CREATE TABLE EMP (EMPNO NUMBER(4) primary key, ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4), HIREDATE DATE, SAL NUMBER(7,2), COMM NUMBER(7,2), DEPTNO NUMBER(2));
DEPT表およびEMP表には、それぞれ次のデータ行が設定されています。
DEPTNO DNAME LOC ------- ---------- --------- 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ----- ------- --------- ------ --------- ------ ------ ------- 7369 SMITH CLERK 7902 17-DEC-80 800 20 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30 7566 JONES MANAGER 7839 02-APR-81 2975 20 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 7782 CLARK MANAGER 7839 09-JUN-81 2450 10 7788 SCOTT ANALYST 7566 19-APR-87 3000 20 7839 KING PRESIDENT 17-NOV-81 5000 10 7844 TURNER SALESMAN 7698 08-SEP-81 1500 30 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 7900 JAMES CLERK 7698 03-DEC-81 950 30 7902 FORD ANALYST 7566 03-DEC-81 3000 20 7934 MILLER CLERK 7782 23-JAN-82 1300 10
埋込みSQLについては、プログラム例を見るとよくわかります。次のプログラムは、demo
ディレクトリのSAMPLE1.PCOです。
プログラムでデータベースにログインし、従業員番号を入力すると、従業員名、給与およびコミッションをEMP表に問い合せます。選択の結果はホスト変数EMP-NAME、SALARYおよびCOMMISSIONに格納されます。また、ホスト標識変数COMM-INDを使用して列COMMISSION内のNULL値を検出します。「標識変数」を参照してください。
次に、段落DISPLAY-INFOによって結果が表示されます。
COBOL変数USERNAME、PASSWDおよびEMP-NAMEは、VARYING句によって宣言されます。VARYING句により、VARCHARという可変長文字列のOracle外部データ型を使用できます。このデータ型は、「VARCHAR変数」を参照してください。
エラー処理のためにSQLCAコミュニケーション領域が組み込まれています。エラーが発生すると、段落SQL-ERRORが実行されます。「SQLコミュニケーション領域の使用」を参照してください。
ここで使用されているBEGIN DECLARE SECTION文およびEND DECLARE SECTION文は、プリコンパイラ・オプションDECLARE_SECTIONがYES、またはオプションMODEがANSIに設定されていない場合、省略できます。「MODE」を参照してください。
エラー処理のためにWHENEVER文を使用しています。詳細は、「WHENEVERディレクティブ」を参照してください。
このプログラムは、従業員番号として0(ゼロ)を入力すると終了します。
注意: この機能を簡単に示すために、この例では、通常デプロイされたシステムで使用されるパスワード管理技術を実行しません。本番環境では、Oracle Databaseのパスワード管理のガイドラインに従って、すべてのサンプル・アカウントを無効にしてください。パスワード管理のガイドラインおよび他のセキュリティの推奨事項については、『Oracle Databaseセキュリティ・ガイド』を参照してください。 |
* This program logs on to ORACLE, prompts the user for an employee number, * queries the database for the employee's name, salary, and commission, then * displays the result. The program terminates when the user enters a 0. * ID DIVISION. PROGRAM-ID. QUERY. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 USERNAME PIC X(10) VARYING. 01 PASSWD PIC X(10) VARYING. 01 EMP-REC-VARS. 05 EMP-NAME PIC X(10) VARYING. 05 EMP-NUMBER PIC S9(4) COMP VALUE ZERO. 05 SALARY PIC S9(5)V99 COMP-3 VALUE ZERO. 05 COMMISSION PIC S9(5)V99 COMP-3 VALUE ZERO. 05 COMM-IND PIC S9(4) COMP VALUE ZERO. EXEC SQL END DECLARE SECTION END-EXEC. EXEC SQL INCLUDE SQLCA END-EXEC. 01 DISPLAY-VARIABLES. 05 D-EMP-NAME PIC X(10). 05 D-SALARY PIC Z(4)9.99. 05 D-COMMISSION PIC Z(4)9.99. 05 D-EMP-NUMBER PIC 9(4). 01 D-TOTAL-QUERIED PIC 9(4) VALUE ZERO. PROCEDURE DIVISION. BEGIN-PGM. EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. PERFORM LOGON. QUERY-LOOP. DISPLAY " ". DISPLAY "ENTER EMP NUMBER (0 TO QUIT): " WITH NO ADVANCING. ACCEPT D-EMP-NUMBER. MOVE D-EMP-NUMBER TO EMP-NUMBER. IF (EMP-NUMBER = 0) PERFORM SIGN-OFF. MOVE SPACES TO EMP-NAME-ARR. EXEC SQL WHENEVER NOT FOUND GOTO NO-EMP END-EXEC. EXEC SQL SELECT ENAME, SAL, NVL(COMM, 0) INTO :EMP-NAME, :SALARY, :COMMISSION:COMM-IND FROM EMP WHERE EMPNO = :EMP-NUMBER END-EXEC. PERFORM DISPLAY-INFO. ADD 1 TO D-TOTAL-QUERIED. GO TO QUERY-LOOP. NO-EMP. DISPLAY "NOT A VALID EMPLOYEE NUMBER - TRY AGAIN.". GO TO QUERY-LOOP. LOGON. MOVE "SCOTT" TO USERNAME-ARR. MOVE 5 TO USERNAME-LEN. MOVE "TIGER" TO PASSWD-ARR. MOVE 5 TO PASSWD-LEN. EXEC SQL CONNECT :USERNAME IDENTIFIED BY :PASSWD END-EXEC. DISPLAY " ". DISPLAY "CONNECTED TO ORACLE AS USER: ", USERNAME-ARR. DISPLAY-INFO. DISPLAY " ". DISPLAY "EMPLOYEE SALARY COMMISSION". DISPLAY "-------- ------ ----------". MOVE EMP-NAME-ARR TO D-EMP-NAME. MOVE SALARY TO D-SALARY. IF COMM-IND = -1 DISPLAY D-EMP-NAME, D-SALARY, " NULL" ELSE MOVE COMMISSION TO D-COMMISSION DISPLAY D-EMP-NAME, D-SALARY, " ", D-COMMISSION END-IF. SIGN-OFF. DISPLAY " ". DISPLAY "TOTAL NUMBER QUERIED WAS ", D-TOTAL-QUERIED, ".". DISPLAY " ". DISPLAY "HAVE A GOOD DAY.". DISPLAY " ". EXEC SQL COMMIT WORK RELEASE END-EXEC. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. STOP RUN.