ヘッダーをスキップ
Pro*COBOL®プログラマーズ・ガイド
11gリリース2(11.2)
E50141-01
  ドキュメント・ライブラリへ移動
ライブラリ
製品リストへ移動
製品
目次へ移動
目次
索引へ移動
索引

前
 
次
 

2 プリコンパイラの概念

この章では埋込みSQLプログラムの動作を説明します。重要な用語の定義、基本概念の説明および主なルールを示します。

内容は次のとおりです。

埋込みSQLプログラミングの基本概念

この項では、後の各章で説明する内容の基本概念について説明します。

埋込みSQLアプリケーションの開発ステップ

プリコンパイルを実行すると、通常どおりにコンパイルできるソース・ファイルが生成されます。プリコンパイルを行うと従来の開発過程より1ステップ処理が増えますが、これによって柔軟性に富んだアプリケーションを開発できるという大きな利点があります。

図2-1は、埋込みSQLアプリケーションの開発過程を示しています。

図2-1 アプリケーションの開発過程

開発過程
「図2-1 アプリケーションの開発過程」の説明

埋込みSQL文

埋込みSQLとは、アプリケーション・プログラムに記述されているSQL文のことです。SQL文を含むアプリケーション・プログラムはホスト・プログラムと呼ばれ、その記述言語はホスト言語と呼ばれます。たとえば、Pro*COBOLでは、SQL文をCOBOLホスト・プログラムに埋め込むことができます。

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文を記述するために特に必要なことは、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文および固定的なトランザクションを処理するように設計されています。この場合、処理を実行する前に各SQL文およびトランザクションの構成がわかります。つまり、発行されるSQLコマンド、変更されるデータベースの表、更新される列などが事前にわかります。第5章「埋込みSQL」を参照してください。

しかし、実行時に有効なSQL文を受け入れて処理する必要のあるアプリケーションもあります。この場合、関係するSQLコマンド、データベースの表および列は実行時までわからない場合もあります。

動的SQLは、プログラムの実行時にSQL文を受け取るかまたは作成し、データ型変換を明示的に管理する高度なプログラミング技術です。第9章「Oracle動的SQL」第10章「ANSI動的SQL」および第11章「Oracle動的SQL: 方法4」を参照してください。

埋込みPL/SQLブロック

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「内部データ型と外部データ型の間での変換」は、必要に応じてOracleによって自動的に変換される、互換性のあるデータ型を示しています。

Oracleデータ型

一般的に、ホスト・プログラムはデータベースにデータを入力し、データベースはホスト・プログラムにデータを出力します。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)

SQLCODE/SQLSTATE状態変数

SQL文の実行後、OracleサーバーはSQLCODEまたはSQLSTATEという変数にステータス・コードを戻します。ステータス・コードは、そのSQL文の実行に成功したか、エラーまたは警告状態が発生したかを示します。

SQLCA状態変数

SQLCAは、Oracleでプログラムにランタイム・ステータス情報を渡すために使用されるプログラム変数を定義するデータ構造体です。SQLCAを使用すると、直前に試みた処理に関するOracleからのフィードバックに基づいて、異なる処理を実行できます。たとえば、DELETE文が成功したかチェックし、成功した場合は削除された行数をチェックできます。

SQLCAによって、診断チェックおよびイベント処理ができます。実行時には、Oracleからプログラムに渡されるステータス情報をSQLCAで保持します。SQL文の実行後、Oracleにより図2-2に示すようにSQLCA変数が設定されて、結果が示されます。

図2-2 SQLCAの更新

SQLCAの更新
「図2-2 SQLCAの更新」の説明

INSERT文、UPDATE文またはDELETE文の実行の成否を確認でき、成功した場合には、何行処理されたかを確認できます。文の実行に失敗した場合は、原因の詳細な情報が得られます。

MODE={ANSI13 | ORACLE}のとき、SQLCAを宣言するには、SQLCAをハードコーディングするか、INCLUDE文を使用してプログラムにコピーする必要があります。SQLCAの宣言および使用方法は、「SQLコミュニケーション領域の使用」を参照してください。

WHENEVER文

WHENEVER文を使用すると、Oracleがエラーまたは警告状態を検出した際に自動的に行われるアクションを指定できます。アクションには、次の文から続行、サブプログラムのコール、ラベル付きの命令への分岐、段落の実行、停止などがあります。

ORACA

ランタイム・エラーについて、SQLCAに格納されている情報よりも詳細な情報が必要なときにORACAを使用します。ORACAは、Oracleの通信を扱うデータ構造です。この中にはカーソル統計情報、現行のSQL文に関する情報、オプションの設定、およびシステムの統計情報が含まれます。

プリコンパイラ・オプションおよびエラー処理

Oracleは、SQL文が成功したか失敗したかについて、状態変数SQLSTATEおよびSQLCODEで戻します。プリコンパイラ・オプションMODE=ORACLEのときは、SQLCAを組み込むことによってSQLCODEを宣言できます。MODE=ANSIの場合はSQLSTATEまたはSQLCODEを宣言する必要がありますが、SQLCAの宣言は不要です。

詳細は、第8章「エラー処理および診断」を参照してください。

SQL99構文のサポート

SQL規格により、規格に準拠するすべてのソフトウェア製品で、SQLアプリケーションを移植できます。Oracle機能は、ANSI/ISO SQL99規格(ANSI準拠の結合を含む)に準拠しています。Pro*Cobolでは、Oracle DatabaseでサポートされているすべてのSQL99機能がサポートされており、SELECT文、INSERT文、DELETE文およびUPDATE文と、DECLARE CURSOR文でのカーソル本体のSQL99構文がサポートされています。

プログラミング・ガイドライン

この項では、埋込みSQLの構文、コーディング規則、Pro*COBOL固有の機能および制限事項を説明します。簡単に参照できるように、項目をアルファベット順に記載してします。

略称

COBOLの標準略称を使用できます。たとえば、PICTURE ISをPIC、USAGE IS COMPUTATIONALをCOMPと記述できます。

大/小文字の区別なし

Pro*COBOLプリコンパイラのオプションと値、EXEC SQL文、インライン・コマンドおよびCOBOL文には大文字と小文字の区別がありません。プリコンパイラは大文字のトークンも小文字のトークンも受け入れます。

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コンパイラのマニュアルを参照してください。


注意:

このマニュアルのサンプルCOBOLコードでは、FORMAT=TERMINALに設定しています。デモ・ディレクトリのオンライン・サンプル・プログラムではFORMAT=ANSIになっています。

カンマ

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文

Copy文はPro*COBOLでは解析されません。そのため、COPY命令に含まれるファイルには、ホスト変数の定義を含めることも、埋込みSQL文を含めることもできません。かわりに、「INCLUDE文の使用」で説明しているINCLUDEプリコンパイラ文を使用します。INCLUDEを使用し、さらにDECLARE_SECTION=YESも使用する際には注意してください。グループ項目は、すべて宣言部の内部に配置するか、あるいはすべて外部に配置する必要があります。

DECIMAL-POINT IS COMMA句

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.

埋込みSQLの構文

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を使用できます。ワードFILLERは、明示的に参照できないグループの基本項目を指定するときに使用します。次の宣言は有効です。

 01  STOCK. 
     05  DIVIDEND     PIC X(5).
     05  FILLER       PIC X.
     05  PRICE        PIC X(6).

ホスト変数名

ホスト変数には、有効な標準COBOL識別子であればどれでも使用できます。変数名の長さに制限はありませんが、最初の30文字のみ有効になります。COBOLコンパイラが認識する有効文字の最大数は30です。

移植性を考慮する場合は、ホスト変数名を18文字以下(SQL標準での長さの要件)に制限することもできます。

アプリケーションで使用制限があるワードの一覧は、付録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のデフォルト

MAXLITERALオプションを使用して、Pro*COBOLで生成される文字列リテラルの最大長を指定して、コンパイラ制限を超えないようにします。Pro*COBOLの場合はデフォルト値は256ですが、これより小さい値の指定が必要な場合もあります。IBM独自のS370オペレーティング・システムでは120です。

マルチバイト・データ型

マルチバイト・キャラクタ・データを扱うために、ANSI規格の各国語キャラクタ・セットのデータ型がサポートされています。使用しているコンパイラでPIC N句またはPIC G句がサポートされている場合は、これらの句によって固定長のNCHAR文字列を格納する変数が定義されます。可変長のマルチバイト各国語キャラクタ・セット文字列を格納するには、長さフィールドおよび文字列フィールドから構成されるCOBOLグループ項目を使用します。「VARCHAR変数」を参照してください。

クライアント側のグローバリゼーション・サポート各国語キャラクタ・セットを指定するために環境変数NLS_NCHARを使用できます。

SQLのNULL

SQLにおいて、NULLは欠落した、不明な、または不適切な列の値を表します。ゼロや空白に相当するものではありません。NVL関数を使用してNULLを非NULL値へ変換し、IS [NOT] NULL比較演算子を使用して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. 
     ... 

段落の名前は、すべて領域Aから始めます。

REDEFINES句

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は警告もエラーも発行しません。

関係演算子

表2-2のように、COBOLの関係演算子はそれに対応するSQLの関係演算子と異なります。また、COBOLでは記号のかわりにワードを使用できますが、SQLでは使用できません。

表2-2 関係演算子

SQL演算子 COBOL演算子

=


=、EQUAL TO

< >, !=, ^=

NOT=、NOT EQUAL TO

>

>、GREATER THAN

<


<、LESS THAN

>=

>=、GREATER THAN OR EQUAL TO

<=


<=、LESS THAN OR EQUAL TO




文終了記号

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.

この2つの文の間に指定できるのは、次の要素のみです。

  • ホスト変数および標識変数の宣言

  • ホスト変数以外の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.

プリコンパイラ・オプションDECLARE_SECTION

宣言部はオプションです。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文の使用

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> ... 

複数のパスを指定すると、Pro*COBOLにより、カレント・ディレクトリ、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を使用することができます。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文は同様に動作します。

注意: 再帰的なネストされたプログラムは、サポートされていません。

SQLCAの宣言

ネストされたプログラムでは、提供される組込みSQLCA (「SQLCA状態変数」を参照)の定義はグローバルとして宣言されるため、SQLCAの宣言は上位プログラム内でのみ必要になります。SQLCAは、新しいSQL文が実行されるたびに変更できます。提供されるSQLCAはいつでも変更できるため、ネストされたプログラムで追加のSQLCA領域を宣言する場合にはグローバル指定を削除できます。これはSQLDAおよびORACAにも適用されます。

ネストされたプログラムの例

デモ・ディレクトリのSAMPLE13.PCOを参照してください。

条件付きプリコンパイル

条件付きプリコンパイルとは、特定の条件に基づいてコード・セクションをホスト・プログラムに組み込む(または除外する)プリコンパイルの方法です。たとえば、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つのファイルの中で宣言したカーソルを、別のファイルでオープンまたはフェッチすることはできません。分割プリコンパイルを実行するときは、指定のカーソルに対する定義と参照がすべて1つのファイルに記述されているか確認してください。

MAXOPENCURSORSの指定

Oracleに接続するプログラム・モジュールをプリコンパイルするときは、MAXOPENCURSORSに、どのプログラム・モジュールについても十分な大きさの値を指定してください。指定したMAXOPENCURSORSの値は、別のプログラム・モジュールに使用すると無視されます。実行時には、その接続に有効な値のみ使用されます。

単一のSQLCAの使用

SQLCAの1つのメモリー領域のみを使用する場合の処理は、使用するPro*COBOLのバージョンによって異なります。

バージョン1.8以下

SQLCAをグローバルに宣言する必要があります。そのためには、次の行を変更してSQLCA.COBファイルを修正します。

 01  SQLCA.

これを次のように変更します。

 01  SQLCA EXTERNAL.

SQLCA.cobからコピーしたSQLCAのハードコード定義を組み込み、前述の変更を行う方法もあります。その場合も、SQLCAの定義をすべてのプリコンパイル・ユニットに組み込む必要があります。

バージョン2以上

バージョン2以上のPro*COBOLでは、SQLCAがファイル・システムからコピーされません。プリコンパイラによって生成されます。これらのバージョンでSQLCA構造を共有する必要がある場合は、次の文を使用しません。

EXEC SQL INCLUDE SQLCA END-EXEC

かわりに、次のコードを使用します。

EXEC SQL INCLUDE SQLCA.ANX END-EXEC

これにより、プリコンパイラによってSQLCA構造が生成され、EXTERNALキーワードが自動的に追加されます。

単一のDATE_FORMATの使用

各プログラム・モジュールでは、DATEに同じ書式の文字列を使用する必要があります。

制限

明示カーソルの参照は、すべて同じプログラム・ファイル内で行います。別のモジュールで宣言されたカーソルの操作はできません。カーソルの詳細は、第4章を参照してください。

また、SQL文が記述されているプログラム・ファイルはすべて、ローカルSQL文のスコープ内にあるSQLCAを必要とします。

コンパイルおよびリンク

実行可能プログラムを作成するには、Pro*COBOLによって生成されたソース・ファイルをコンパイルし、その結果得られたオブジェクト・モジュールを、SQLLIBおよびシステム固有のOracleライブラリ内の必要なモジュールとリンクさせる必要があります。

リンカーはオブジェクト・モジュール内のシンボリック参照を解決します。これらの参照で競合が発生すると、リンクは失敗します。プリコンパイル済のプログラムにサード・パーティのソフトウェアをリンクするときに、このような競合が起こる可能性があります。こうした問題が生じるのは、サード・パーティのソフトウェアの中にはOracleと互換性のないものがあるためです。Oracleサポート・サービスに問い合せて、使用するソフトウェアがサポートされているかどうかを確認してください。

コンパイルおよびリンクの方法はシステムによって異なります。たとえば、システムによっては、ホスト言語プログラムをコンパイルするときにコンパイラの最適化をオフにする必要があります。手順は、使用しているシステム固有のOracleマニュアルを参照してください。

DEPT表およびEMP表のサンプル

このマニュアルで紹介するほとんどのプログラム例では、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データのサンプル

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

サンプルEMPプログラム: SAMPLE1.PCO

埋込み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.