この章では、埋込みSQL文により提供されるLOB (ラージ・オブジェクト)データ型のサポートについて記述します。4種類のLOB型を説明し、従来のLONGおよびLONG RAWデータ型と比較します。
Pro*COBOLの埋込みSQLインタフェースは、PL/SQL言語と同様の機能を提供します。
LOB文およびそのLOBオプションとホスト変数を説明します。
LOBインタフェースを使用したPro*COBOLによるプログラミング例を説明します。
内容は次のとおりです。
LOB (ラージ・オブジェクト)とは、ASCIIテキスト、各国文字のテキスト、様々なグラフィック・フォーマットのファイルおよびサウンド波形などの大量のデータ(最大4GB)を格納するために使用されるデータベース型のことです。
内部LOB (BLOB、CLOB、NCLOB)はデータベースの表領域に格納されます。また、内部LOBでは、データベース・サーバーのトランザクション・サポートが有効です。(COMMIT、ROLLBACKなどを使用できます。)
BLOB(Binary LOB)には、ビデオ・クリップなどの非構造化バイナリ(「ロー」とも呼ばれます)・データが格納されます。
CLOB(Character LOB)には、データベース・キャラクタ・セットの文字列データのラージ・ブロックが格納されます。
NCLOB(National Character LOB)には、各国語キャラクタ・セットの文字列データのラージ・ブロックが格納されます。
外部LOBは、データベース表領域外のオペレーティング・システム・ファイルです。ただし、データベース・サーバーのトランザクション・サポートは無効です。
BFILE(Binary Files)では、データは外部バイナリ・ファイルの形式で格納されます。BFILEでは、GIF、JPEG、MPEG、MPEG2、テキストなどのフォーマットを扱うことができます。
DIRECTORYオブジェクトは、BFILEに対するアクセスや使用のために使用します。DIRECTORYは、ファイルが格納されているサーバー・ファイル・システムの実際の物理ディレクトリの(サーバーに格納されている)論理的な別名です。DIRECTORYオブジェクトに対するアクセス権限が割り当てられているユーザー以外は、ファイルにアクセスできません。
BFILEで使用できるSQL文は、次の2種類です。
データ定義言語(DDL) SQL文のCREATE、REPLACE、ALTERおよびDROP
DIRECTORYオブジェクト上のシステムおよびオブジェクトに対するREAD権限のGRANTおよびREVOKEを行うデータ操作言語(DML)SQL文
CREATE DIRECTORYディレクティブの例を、次に示します。
EXEC SQL CREATE OR REPLACE DIRECTORY "Mydir" AS '/usr/home/mydir' END-EXEC.
ユーザーまたはロールは、GRANTなどのデータ操作言語(DML)文の権限が割り当てられている場合にのみ、ディレクトリを読み込むことができます。たとえば、ユーザーscott
がディレクトリ/usr/home/mydir
のBFILESを読み込めるようにするには次のようにします。
EXEC SQL GRANT READ ON DIRECTORY "Mydir" TO scott END-EXEC.
1セッション内で、最大10個のBFILESを同時にオープンできます。SESSION_MAX_OPEN_FILESパラメータの設定を変更して、デフォルト値を変更できます。
DIRECTORYオブジェクト、BFILEセキュリティおよびGRANTコマンドの詳細は、『Oracle Databaseアドバンスト・アプリケーション開発者ガイド』を参照してください。
LOBは、従来のLONGおよびLONG RAWデータ型と多くの点で異なります。
LOBの最大サイズは4GBです。LONGおよびLONG RAWの最大サイズは2GBです。
LOBでは、ランダム・アクセス方法および順次アクセス方法を使用できます。LONGおよびLONG RAWでは、順次アクセス方法のみです。
LOB (NCLOBは除きます)は、定義したオブジェクト型の属性になります。
表では複数のLOB列を作成できますが、複数のLONGまたはLONG RAW列は作成できません。
既存のLONGおよびLONG RAW属性は、LOBに移行することをお薦めします。今後のリリースでは、LONGおよびLONG RAWはサポートしない予定です。関連項目: 移行の詳細は『Oracle Databaseアップグレード・ガイド』を、LOBの詳細は『Oracle Database SecureFilesおよびラージ・オブジェクト開発者ガイド』を参照してください。
LOBロケータによって、実際のLOB内容がポイントされます。ロケータはLOBの内容ではなくLOBを取り出したときに戻されます。LOBロケータは、特定のトランザクションまたはセッションには保存されずに、後続のトランザクションまたはセッションで再使用されます。
LOBデータベースを使用しやすくするために、一時LOBを作成できます。一時LOBはローカル変数に似ていますが、表には関連付けられていません。一時LOBを作成したユーザーのみがロケータを使用してアクセスでき、セッションが終了すると削除されます。
一時BFILEはサポートされていません。一時LOBはINSERT文のWHERE句、UPDATEのSET句、またはDELETE文のWHERE句の入力変数(IN値)としてのみ使用できます。一時LOBではデータベース・サーバーのトランザクション・サポートが無効なため、COMMITまたはROLLBACKを行うことはできません。
一時LOBロケータは、トランザクションをまたがって使用することができます。一時LOBは、サーバーが異常終了したとき、およびデータベースSQL操作からエラーが戻されたときは削除されます。
LBS (LOB Buffering Subsystem)は、クライアントのアドレス空間で1つまたは複数のLOBバッファとして使用するためのユーザー・メモリー領域です。
バッファリングには次の利点があります。特に、LOBの特定領域に小規模な読取りおよび書込みを繰り返すクライアントのアプリケーションに有効です。
LOBに対する複数の読取り/書込みをバッファに蓄積し、FLUSHディレクティブが実行されたときにサーバーに書き込むため、サーバーへのラウンドトリップが減少します。
サーバー上でのLOBの合計更新数が減少します。この結果、LOBのパフォーマンスが向上し、ディスク領域が節約されます。
このバッファリングは、簡単なバッファ・サブシステムで、キャッシュではありません。バッファの内容が、サーバーのLOB値と常に同期しているとはかぎりません。サーバーのLOBに実際に更新を書き込むには、FLUSH文を使用します。
LOBのバッファへの読取り/書込みは、ロケータを使用して実行されます。バッファリングが使用可能なロケータを使用すると、書込みを実行するまで、LOBを常に読み込むことができます。
ロケータは、WRITEのバッファに使用された後で更新され、バッファリング・サブシステムを介して表示できる最新のLOBに対するアクセス権限が割り当てられます。これ以降のバッファされたLOBへのWRITEは、更新されたロケータを使用しないとできません。バッファされたLOBの操作を行うトランザクションは、ユーザー・セッション間では移行できません。
LBSは、サーバーのLOB値をFLUSH文を使用して更新するユーザーが管理します。LBSは、シングル・ユーザーでシングル・スレッドです。サーバーLOBの妥当性を確保するには、ROLLBACKおよびSAVEPOINTアクションを使用します。バッファされたLOB操作のトランザクション・サポートは無効です。バッファされたLOB更新のトランザクション・セマンティクスを確保するには、エラー発生時にロールバックを行う論理セーブポイントをメンテナンスする必要があります。
LBSの詳細は、『Oracle Databaseアドバンスト・アプリケーション開発者ガイド』を参照してください。
Pro*COBOLからLOBにアクセスするには、次の2つの方法があります。
PL/SQLブロックのDBMS_LOBパッケージ
埋込みSQL文
埋込みSQL文は、PL/SQLインタフェースと同じ機能を使用できるように設計されています。
次の表では、PL/SQLからのLOBアクセスおよびPro*COBOLの埋込みSQL文を比較します。ハイフンは、機能がないことを示します。
表13-1 LOBへのアクセス方法
PL/SQL脚注 1 | Pro*COBOLの埋込みSQL |
---|---|
COMPARE() |
- |
INSTR() |
- |
SUBSTR() |
- |
APPEND() |
APPEND |
:= |
ASSIGN |
CLOSE() |
CLOSE |
COPY() |
COPY |
CREATETEMPORARY() |
CREATE TEMPORARY |
- |
DISABLE BUFFERING |
- |
ENABLE BUFFERING |
ERASE() |
ERASE |
GETCHUNKSIZE() |
DESCRIBE |
ISOPEN() |
DESCRIBE |
FILECLOSE() |
CLOSE |
FILECLOSEALL() |
FILE CLOSE ALL |
FILEEXISTS() |
DESCRIBE |
FILEGETNAME() |
DESCRIBE |
FILEISOPEN() |
DESCRIBE |
FILEOPEN() |
OPEN |
BFILENAME() |
FILE SET脚注 2 |
- |
FLUSH BUFFER |
FREETEMPORARY() |
FREE TEMPORARY |
GETLENGTH() |
DESCRIBE |
= |
- |
ISTEMPORARY() |
DESCRIBE |
LOADFROMFILE() |
LOAD FROM FILE |
OPEN() |
OPEN |
READ() |
READ |
TRIM() |
TRIM |
WRITE() |
WRITE |
WRITEAPPEND() |
WRITE |
脚注 1 dbmslob.sqlからコールします。BFILENAMEを除くルーチンの前には、すべて'DBMS_LOB'を付ける必要があります。
脚注 2 SQL関数に組み込まれているBFILENAME()も使用できる場合があります。
注意: 新しい文を使用する前に、LOBに対して修正または変更する行を明示的にロックする必要があります。LOB値を修正する操作には、APPEND、COPY、ERASE、LOAD FROM FILE、TRIMおよびWRITEがあります。 |
Pro*COBOLアプリケーションでLOBロケータを使用するには、次の擬似タイプを使用します。
SQL-BLOB
SQL-CLOB
SQL-NCLOB
SQL-BFILE
MY-NCLOBと呼ばれるNCLOB変数を宣言するには、次のようにします。
01 MY-NCLOB SQL-NCLOB.
この項では、様々なLOBの初期化方法を説明します。
BLOBを初期化して空にするには、EMPTY_BLOB()関数またはALLOCATE SQL文を使用します。CLOBおよびNCLOBには、EMPTY_CLOB()関数を使用します。EMPTY_BLOB()およびEMPTY_CLOB()の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。これらの関数は、INSERT文のVALUES句内またはUPDATE文のSET句のソースでのみ使用できます。
次に例を示します。
EXEC SQL INSERT INTO lob_table (a_blob, a_clob) VALUES (EMPTY_BLOB(), EMPTY_CLOB()) END-EXEC.
ALLOCATE文は、LOBロケータを割り当て、初期化して空にします。次のコードは、前の例と同じです。
... 01 A-BLOB SQL-BLOB. 01 A-CLOB SQL-CLOB. ... EXEC SQL ALLOCATE :A-BLOB END-EXEC. EXEC SQL ALLOCATE :A-CLOB END-EXEC. EXEC SQL INSERT INTO lob_table (a_blob, a_clob) VALUES (:A-BLOB, :A-CLOB) END-EXEC.
BFILEおよびFILENAMEのDIRECTORY別名を初期化するには、LOB FILE SET文を次のように使用します。
... 01 ALIAS PIC X(14) VARYING. 01 FILENAME PIC X(14) VARYING. 01 A-BFILE SQL-BFILE. ... MOVE "lob_dir" TO ALIAS-ARR. MOVE 7 TO ALIAS-LEN. MOVE "image.gif" TO FILENAME-ARR MOVE 9 TO FILENAME-LEN.. EXEC SQL ALLOCATE :A-BFILE END-EXEC. EXEC SQL LOB FILE SET :A-BFILE DIRECTORY = :ALIAS, FILENAME = :FILENAME END-EXEC. EXEC SQL INSERT INTO file_table (a_bfile) VALUES (:A-BFILE) END-EXEC.
DIRECTORYオブジェクトのネーミング規則およびDIRECTORYオブジェクト権限の詳細は、『Oracle Databaseアドバンスト・アプリケーション開発者ガイド』を参照してください。
また、INSERTまたはUPDATE文のBFILENAME('ディレクトリ', 'ファイル名')機能を使用して、BFILE列または特定行の属性を初期化し、実際の物理ディレクトリおよびファイル名を取得できます。
EXEC SQL INSERT INTO file_table (a_bfile) VALUES (BFILENAME('lob_dir', 'image.gif')) RETURNING a_bfile INTO :A-BFILE END-EXEC.
注意: BFILENAME()では、ディレクトリまたはファイル名の権限、および物理ディレクトリの有無は確認されません。BFILEロケータを使用してファイルにアクセスしたときに、これらが確認され、ファイルにアクセスできない場合にはエラーが戻されます。 |
LOB文を使用するときのルールを説明します。
次の一般的な制限および制約は、SQL LOB文を使用してLOBを操作するときに適用されます。
埋込みSQLのLOB文では、FOR句は使用できません。これらの文は、単一のLOBロケータのみ使用できます。ただし、ALLOCATEおよびFREE文では、FOR句を使用できます。
分散LOBはサポートされていません。新規の埋込みSQL LOB文であればATデータベース句を使用できますが、異なったデータベース接続を使用して作成または割り当てられたLOBロケータを、同一SQL LOB文内で併用することはできません。
LBSでは、次のルールに従う必要があります。
読取りまたは書込みアクセス時のエラーは、次回のサーバーへのアクセス時にレポートされます。このため、エラー・リカバリのコードは、ユーザーが作成する必要があります。
バッファへの書込みによりLOBを更新するときは、必ずLOBバッファリング・サブシステムを経由して更新を行ってください。
バッファリングが可能な更新済LOBロケータは、INパラメータとしてPL/SQLプロシージャに渡せますが、IN OUTあるいはOUTパラメータとしては渡すことはできません。エラーが戻されます。更新済ロケータを戻そうとしたときにも、エラーが戻されます。
バッファリング可能な更新済ロケータを、別のロケータにはASSIGNできません。
バッファへの書込みをLOB値に追加することができますが、その開始オフセットの1文字は、LOBの最後に続く必要があります。LBSでは、データベース・サーバーのLOBに、0バイトの充填文字または空白が入るAPPEND文は使用できません。
ホスト・ロケータのバインド変数のキャラクタ・セットとデータベース・サーバーのCLOBは、同じであることが必要です。
ASSIGN、READおよびWRITE文のみ、バッファリング可能なロケータとともに使用できます。
バッファリング可能なロケータでAPPEND、COPY、ERASE、DESCRIBE (LENGTHのみ)、SELECTおよびTRIMの文を使用すると、エラーになります。また、これらの文をバッファリング不可能なロケータとともに使用した場合でも、そのロケータによってポイントされたLOBが他のロケータによってバッファ・モードでアクセスされた場合には、エラーが戻されます。
注意: FLUSH文をLOBで使用するときは、次の処理の前に、LOBバッファリング・サブシステムでLOBが使用可能になっている必要があります。 |
トランザクションのコミット
カレント・トランザクションから他のトランザクションへの移行
LOB上でのバッファ操作の使用禁止
srcおよびdstを使用して、内部または外部LOBロケータを参照できますが、fileでは、外部ロケータ以外は参照できません。
数値のホスト値(amt、src_offset、dst_offset
など)は、4バイトの整変数PIC S9(9) COMPとして宣言されます。値は、0から4GBに制限されています。
NULLは、LOBロケータで使用します。LOB文では標識変数は必要ありません。NULLは、数値変数(amt、src_offset
など)には使用できません。エラーが発生します。
オフセット値src_offset
およびdst_offset
のデフォルト値は1です。
注意: 変数BLOB、CLOBおよびNCLOBは、使用するプラットフォームの位置合せの要件に従って使用する必要があります。使用するプラットフォームの位置合せの制限の詳細は、そのプラットフォームのマニュアルを参照してください。 |
アルファベット順に文を説明します。すべての説明文で、databaseはデータベース接続を示します。
用途
APPEND文では、別のLOBの最後にLOB値を追加します。
構文
EXEC SQL [AT [:]database] LOB APPEND :src TO :dst END-EXEC.
ホスト変数
ソースLOBを一意に参照する内部LOBロケータ。
宛先LOBを一意に参照する内部LOBロケータ。
使用上の注意
ソースLOBのデータが宛先LOBの最後にコピーされると、宛先LOBが最大4GBまで拡張されます。LOBが4GBを超えて拡張される場合は、エラーが発生します。
ソースおよび宛先LOBは、すでに存在している必要があります。また、宛先LOBは初期化されている必要があります。
ソースおよび宛先LOBの両方が、同じ内部LOB型であることが必要です。どちらのロケータに対しても、LOBバッファリングを有効にすると、エラーとなります。
用途
LOBまたはBFILEロケータを、別のロケータに割り当てます。
構文
EXEC SQL [AT [:]database] LOB ASSIGN :src to :dst END-EXEC.
ホスト変数
コピー元のLOBまたはBFILEロケータ・ソース。
コピー先のLOBまたはBFILEロケータ。
使用上の注意
割当て後は、両方のロケータが同じLOB値を参照します。宛先LOBロケータは、有効な初期化された(割り当てられた)ロケータであることが必要です。
内部LOBでは、宛先ロケータが表に格納されている場合にのみ、ソース・ロケータのLOB値が宛先ロケータのLOB値にコピーされます。Pro*COBOLでは、宛先ロケータを格納しているオブジェクトのFLUSHを発行すると、LOB値をコピーします。
BFILEロケータが内部LOBロケータに割り当てられている場合、またはその逆の場合には、エラーが戻されます。src LOBとdst LOBが同じ型でない場合にもエラーになります。
ソース・ロケータがバッファリング可能な内部LOB用であり、かつLOBバッファリング・サブシステムを介してLOB値を変更するために使用されていた場合、またバッファがWRITE後にフラッシュされていない場合には、ソース・ロケータを宛先ロケータに割り当てることはできません。これは、LOBバッファリング・サブシステムを介してLOB値を修正する場合、1つのLOBに対してロケータは1つしか使用できないためです。
用途
オープンされているLOBまたはBFILEをクローズします。
構文
EXEC SQL [AT [:]database] LOB CLOSE :src END-EXEC.
ホスト変数
クローズされるLOBまたはBFILEのロケータ。
使用上の注意
異なるロケータまたは同一ロケータを使用した場合でも、同一LOBを2回クローズするとエラーになります。外部LOBの場合は、BFILEが存在して一度もオープンされていない状態であれば、エラーは発生しません。
オープンしていたLOBをすべてクローズする前に、トランザクションをCOMMITするとエラーになります。トランザクションのROLLBACK時にオープンしているLOBは、クローズされず、すべて破棄されます。
用途
LOB値の全部または一部を別のLOBにコピーします。
構文
EXEC SQL [AT [:]database] LOB COPY :amt FROM :src [AT :src_offset] TO :dst [AT :dst_offset] END-EXEC.
ホスト変数
amt (IN): コピーするBLOBの最大バイト数またはCLOBおよびNCLOBの文字数。
src (IN): ソースLOBのロケータ。
src_offset (IN): CLOBまたはNCLOBの文字数、およびBLOBのバイト数。LOBの先頭で1から始まります。
dst (IN): 宛先LOBのロケータ。
dst_offset (IN): 宛先オフセット。src_offsetと同じルールが適用されます。
使用上の注意
データが宛先のオフセット以降にあらかじめ存在する場合は、ソース・データで上書きされます。宛先のオフセットがカレント・データの最後を超えている場合は、宛先LOBのカレント・データの最後から新しく書き込まれたソース・データの先頭まで、ゼロバイト充填文字(BLOB)または空白(CLOB)が書き込まれます。
新しく書き込まれるデータが宛先LOBの現行の長さを超えている場合は、そのデータを格納できるように宛先LOBが拡張されます。4GBを超えてLOBが拡張されると、ランタイム・エラーが発生します。
初期化されていないLOBからコピーすると、エラーになります。
ソースLOBおよび宛先LOBは、同じ型である必要があります。LOBバッファリングは、両方のロケータに対して使用可能にしないでください。
一時LOBを永続LOBにするには、COPY文を使用して、一時LOBを永続LOBに明示的にCOPYする必要があります。amt
変数はコピーする最大量を示します。指定した量がコピーされる前にソースLOBの最後に到達した場合、エラーを発行せずに操作が終了します。
用途
一時LOBを作成します。
構文
EXEC SQL [AT [:]database] LOB CREATE TEMPORARY :src END-EXEC.
ホスト変数
src (IN OUT): 実行前でINのときは、src
は事前に割り当てられたLOBロケータです。
実行後でOUTになったときは、src
は新しい空の一時LOBをポイントするLOBロケータです。
使用上の注意
実行が正常に終了すると、ロケータはデータベース・サーバーに新しく作成された、表に依存しない一時LOBをポイントします。一時LOBは空で、長さゼロです。
セッション終了時に、すべての一時LOBは解放されます。一時LOBへの読取りおよび書込みは、バッファ・キャッシュを経由しません。
用途
LOBロケータのLOBバッファリングを使用禁止にします。
構文
EXEC SQL [AT [:]database] LOB DISABLE BUFFERING :src END-EXEC.
ホスト変数
src(IN OUT): 内部LOBロケータ。
使用上の注意
この文は、BFILEをサポートしていません。後続の読取りまたは書込みは、LBS経由では行われません。
注意: 変更を永続的なものにするには、FLUSH BUFFERコマンドを使用してください。DISABLE BUFFERING文は、LOBバッファリング・サブシステムが作成した変更を、暗黙的にフラッシュすることはありません。
用途
LOBロケータのLOBバッファリングを使用可能にします。
構文
EXEC SQL [AT [:]database] LOB ENABLE BUFFERING :src END-EXEC.
ホスト変数
src(IN OUT): 内部LOBロケータ。
使用上の注意
この文は、BFILEをサポートしていません。後続の読取りおよび書込みは、LBSを経由して行われます。
用途
指定されたオフセットから始まる、指定された量のLOBデータを消去します。
構文
EXEC SQL [AT [:]database] LOB ERASE :amt
FROM :src [AT :src_offset] END-EXEC.
ホスト変数
amt (IN OUT): 入力は、消去するバイト数または文字数です。戻される出力は、実際に消去されたバイト数または文字数です。
src(IN OUT): 内部LOBロケータ。
src_offset (IN): LOBの開始からのオフセット。1から指定できます。
使用上の注意
この文は、BFILEをサポートしていません。
実行後、消去された実際の文字数またはバイト数がamtから戻されます。要求した文字数またはバイト数を消去する前にLOB値の最後に到達した場合は、実際の消去数と要求した消去数は異なります。LOBが空の場合は、amtは0文字または0バイトが消去されたことを示します。
BLOBの場合は、消去とはゼロバイト充填文字で既存のLOB値を上書きすることです。CLOBの場合は、空白で既存のLOB値を上書きすることです。
用途
カレント・セッションでオープンしているBFILESをすべてクローズします。
構文
EXEC SQL [AT [:]database] LOB FILE CLOSE ALL END-EXEC.
使用上の注意
適切にクローズされなかったオープン・ファイルがセッションに存在する場合は、FILE CLOSE ALL文を使用して、セッションでオープンしているファイルをすべてクローズし、ファイル操作を始めから再開できます。
用途
BFILEロケータのDIRECTORY別名およびFILENAMEを設定します。
構文
EXEC SQL [AT [:]database] LOB FILE SET :file DIRECTORY = :alias, FILENAME = :filename END-EXEC.
ホスト変数
file (IN OUT): DIRECTORY別名およびFILENAMEを設定するBFILEロケータ。
alias (IN): 設定するDIRECTORY名。
filename (IN): 設定するFILENAME。
使用上の注意
指定したBFILEロケータは、この文で使用する前に、ALLOCATEされている必要があります。
DIRECTORY別名およびFILENAMEは必須項目です。
DIRECTORY別名の最大長は30バイトです。FILENAMEの最大長は255バイトです。
DIRECTORY別名およびFILENAME属性がサポートされている外部データ型は、VARCHAR、VARCHAR2およびCHARFのみになります。
この文を外部LOBロケータ以外で使用すると、エラーになります。
用途
LOBのバッファをデータベース・サーバーに書き込みます。
構文
EXEC SQL [AT [:]database] LOB FLUSH BUFFER :src [FREE] END-EXEC.
ホスト変数
src (IN OUT): 内部LOBロケータ。
使用上の注意
入力ロケータが参照するLOBからサーバーのデータベースLOBに、バッファ・データを書き込みます。
LOBバッファリングは、入力LOBロケータに対してすでに有効になっている必要があります。
デフォルトでのFLUSH操作では、バッファ・リソースの解放および別のバッファされたLOB操作への再割当ては行われません。ただし、バッファを明示的に解放する場合は、オプションのFREEキーワードを使用して指定できます。
用途
LOBロケータ用に一時領域を解放します。
構文
EXEC SQL [AT [:]database] LOB FREE TEMPORARY :src END-EXEC.
ホスト変数
src (IN OUT): 一時LOBをポイントするLOBロケータ。
使用上の注意
入力ロケータは、一時LOBをポイントしている必要があります。出力ロケータは、初期化されずに、後続のLOB文で使用されます。
用途
BFILEの一部または全部を、内部LOBにコピーします。
構文
EXEC SQL [AT [:]database] LOB LOAD :amt FROM FILE :file [AT :src_offset] INTO :dst [AT :dst_offset] END-EXEC.
ホスト変数
amt (IN): ロードする最大バイト数。
file (IN OUT): ソースのBFILEロケータ。
src_offset (IN): ファイルの先頭からのオフセット・バイト数。1から指定できます。
dst (IN OUT): 宛先LOBロケータ。BLOB、CLOBおよびNCLOBが有効です。
dst_offset (IN): 書込みが開始する宛先LOBの先頭からのバイト数(BLOBの場合)または文字数(CLOBおよびNCLOBの場合)です。1から始まります。
使用上の注意
データは、ソースBFILEから宛先内部LOBにコピーされます。BFILEデータをCLOBまたはNCLOBにコピーする場合、キャラクタ・セットは変換されません。このため、BFILEデータは、あらかじめデータベース内のCLOBまたはNCLOBと同じキャラクタ・セットになっている必要があります。
ソースおよび宛先LOBは、すでに存在している必要があります。宛先の開始位置にすでにデータがある場合は、ソース・データで上書きされます。宛先の開始位置が現行データの最後を超えている場合は、ゼロバイト充填文字(BLOB)または空白(CLOBおよびNCLOB)が、宛先LOBのデータの最後からソースによって新しく書き込まれたデータの先頭まで書き込まれます。
新しく書き込まれるデータが宛先LOBの現行の長さを超えている場合は、そのデータを格納できるように宛先LOBが拡張されます。4GBを超えてLOBが拡張されると、エラーになります。
また、初期化されていないBFILEからコピーをすると、エラーになります。
amountパラメータは、ロードする最大量を示します。指定した量がロードされる前にソースBFILEの最後に到達した場合は、エラーを発行せずに操作が終了します。
用途
読取り、または読取り/書込みアクセスのために、LOBまたはBFILEをオープンします。
構文
EXEC SQL [AT [:]database] LOB OPEN :src [ READ ONLY | READ WRITE ] END-EXEC.
ホスト変数
src (IN OUT): LOBまたはBFILEのLOBロケータ。
使用上の注意
デフォルト・モードでは、LOBまたはBFILEはREAD ONLYアクセスでオープンされます。
内部LOBの場合は、OPENはロケータではなくLOBに対応付けられます。すでにオープンしているロケータを別のロケータに割り当てても、新規LOBのOPENとしてはカウントされません。両方のロケータから同じLOBが参照されます。BFILEの場合は、OPENはロケータに対応付けられます。
同時にOPENできるLOBの最大数は32個です。33個目のLOBをオープンすると、エラーが戻されます。
書込み可能なBFILEは、サポートしていません。このため、BFILEをREAD WRITEモードでOPENすると、エラーが戻されます。
LOBをREAD ONLYモードでオープンした後にWRITEすると、エラーになります。
用途
LOBまたはBFILEの一部または全部をバッファに読み込みます。
構文
EXEC SQL [AT [:]database] LOB READ :amt FROM :src [AT :src_offset] INTO :buffer [WITH LENGTH :buflen] END-EXEC.
ホスト変数
amt (IN OUT): 入力は、読み込む文字数またはバイト数です。出力は、読み込まれた実際の文字数またはバイト数です。
読み込まれたバイト数がバッファ長より大きい場合は、LOBはポーリング・モードで読み込まれているとみなされます。入力時にこの値がゼロの場合は、データは入力オフセットからLOBの最後までポーリング・モードで読み込まれます。
実際に読み込まれるバイト数または文字数はamt
で戻されます。データがピース単位で読み込まれる場合、amt
には常に最後に読み込まれたピースが含まれます。
LOBの最後に到達すると、「ORA-01403: データが見つかりません。」というエラーが発行されます。
ポーリング・モードで読み込むときは、アプリケーションからLOB READを繰り返しコールし、データがなくなるまでLOBのピースを読み込む必要があります。ORA-01403エラーを捕捉するには、WHENEVERディレクティブでNOT FOUND条件を使用してポーリング・モードを制御してください。
src (IN): LOBまたはBFILEロケータ。
src_offset (IN): これは読込みを開始したLOB値の先頭からの絶対オフセットです。キャラクタLOBにおいては、これはLOBの先頭からの文字数を意味します。バイナリLOBまたはBFILEにおいては、これはバイト数を意味します。最初の位置は1です。
buffer (IN OUT): LOBデータが読み込まれるバッファ。バッファの外部データ型は、ソースLOBの型によって一定の型に制限されます。バッファの最大長は、LOB値を格納するために使用される外部データ型によって決まります。次の表は、有効な外部データ型、およびそのソースLOB型ごとの最大長のリストです。
表13-2 ソースLOBおよびプリコンパイラのデータ型
外部LOB脚注 1 | 内部LOB | プリコンパイラの外部データ型 | プリコンパイラの最大長脚注 2 | PL/SQLデータ型 | PL/SQL最大長 |
---|---|---|---|---|---|
BFILE |
BLOB |
RAW VARRAW LONG RAW LONG VARRAW |
65535 65533 2147483647 2147483643 |
RAW |
32767 |
- |
CLOB |
VARCHAR2 VARCHAR LONG VARCHAR |
65535 65533 2147483643 |
VARCHAR2 |
32767 |
- |
NCLOB |
NVARCHAR2 |
4000 |
NVARCHAR2 |
4000 |
脚注 1 これらの外部データ型は、BFILEで使用できます。
脚注 2 長さは、文字単位ではなく、バイト単位で計算されています。
buflen (IN): 他の方法で長さがわからない場合は、指定したバッファの長さを指定します。
使用上の注意
BFILEは、データベース・サーバーにすでに存在し、入力ロケータを使用してオープンされている必要があります。データベースにはファイルの読取り権限が必要で、ユーザーにはディレクトリの読取り権限が必要になります。
初期化されていないLOBまたはBFILEからの読込みは、エラーとなります。
バッファの長さは、次のように決定されます。
WITH LENGTH句を指定した場合の、buflen
の値。
WITH LENGTH句を指定しなかった場合は、「文字データの処理」のルールに従ってバッファ・ホスト変数をOUTモードで処理すると長さが決定します。
用途
LOB値を切り捨てます。
構文
EXEC SQL [AT [:]database] LOB TRIM :src TO :newlen END-EXEC.
ホスト変数
src (IN OUT): 内部LOB用のLOBロケータ。
newlen (IN): LOB値の新規の長さ。
使用上の注意
この文はBFILEには使用できません。新規の長さは、現行の長さより大きくは設定できません。大きく設定した場合は、エラーが戻されます。
用途
バッファの内容をLOBに書き込みます。
構文
EXEC SQL [AT [:]database] LOB WRITE [APPEND] [ FIRST | NEXT | LAST | ONE ] :amt FROM :buffer [WITH LENGTH :buflen] INTO :dst [AT :dst_offset] END-EXEC.
ホスト変数
amt (IN OUT): 入力は、書き込む文字数またはバイト数です。
出力は、書き込まれた実際の文字数またはバイト数です。
ポーリング・メソッドを使用して書込みをした場合は、WRITE LAST文の実行後に、WRITE文実行時に書き込まれた累積合計長がamt
から戻されます。WRITE文が中断された場合は、amt
は定義されません。
buffer (IN): LOBデータの書込み元のバッファ。データ型の長さについては、「READ」を参照してください。
dst (IN OUT): LOBロケータ。
dst_offset (IN): LOBの先頭からのオフセット(1から始まります)。文字単位の場合はCLOBおよびNCLOB、バイト単位の場合はBLOB。
buflen (IN): 他の方法で計算できなかった場合のバッファ長。
使用上の注意
LOBデータがすでに存在する場合は、バッファに格納されているデータで上書きされます。指定されたオフセットが、現在LOB内にあるデータの最後を超える場合は、ゼロバイト充填文字または空白がLOBに挿入されます。
WRITE文にキーワードAPPENDを指定すると、LOBの最後にデータが自動的に書き込まれます。APPENDを指定すると、宛先オフセットがLOBの最後とみなされます。WRITE文にAPPENDオプションを指定したときに、宛先オフセットを指定するとエラーになります。
バッファは、LOBに対して1ピースで書き込まれるか(デフォルトのONE方向変換を使用します)、標準のポーリング・メソッドを使用してピース単位で書き込むことができます。
FIRSTを使用してポーリングを開始し、NEXTで後続のピースを書き込みます。LASTキーワードは、書込みを終了する最後のピースの書込みに使用します。
このピース単位の書込みモードを使用すると、各ピースのサイズおよび場所が異なる場合に、バッファおよびバッファ長をコール単位に指定できます。
すべての書込みの終了後に渡される合計データ量が、amt
パラメータで指定した量よりも少ない場合は、エラーになります。
同じルールが、READ文のバッファ長の決定にも適用されます。詳細は、「READ」を参照してください。
用途
この文は、いくつかのOCIおよびPL/SQL文と同等です。LOB DESCRIBE SQL文を使用してLOBから属性を取り出します。LOB DESCRIBE文の書式は次のとおりです。
構文
EXEC SQL [AT [:]database] LOB DESCRIBE :src GET attribute1 [{, attributeN}] INTO :hv1 [[INDICATOR] :hv_ind1] [{, :hvN [[INDICATOR] :hv_indN] }] END-EXEC.
次の属性を指定できます。
CHUNKSIZE | DIRECTORY | FILEEXISTS | FILENAME | ISOPEN | ISTEMPORARY | LENGTH
ホスト変数
src (IN): 内部または外部LOBのLOBロケータ。
hv1 ... hvN (OUT): 属性名リストで指定された順番で、属性値を受け取るホスト変数。
hv_ind1 ... hv_indN (OUT): 属性名リストの順番で、NULL状態のインジケータを受け取るオプションのホスト変数。
次の表では、関連するLOBの属性および読込みが必要なCOBOL型を説明します。
表13-3 LOB属性
LOB属性 | 属性の説明 | 制限 | COBOL型 |
---|---|---|---|
LOB値の格納に使用される、指定された表領域ブロックに対する最適なスペース量(BLOBの場合はバイト、CLOBおよびNCLOBの場合は文字)です。チャンク・サイズは固定値ではなく、利用可能なチャンク・サイズに基づいた最大限の値が記憶域に利用されます。同一ページまたは同一ページ・セットで複数のWRITEリクエストを行った場合、データはコミット時のみディスクに書き込まれ、単一の変更として扱われます。これにより、より大きなチャンク・サイズでデータを書き込むことができます。 |
BLOB、CLOBおよびNCLOBのみ |
PIC S9(9) COMP |
|
BFILEの場合は、DIRECTORY別名。長さnは、1から30バイトです。実際の長さを使用します。 |
FILE LOBのみ |
PIC X(n) [VARYING] |
|
BFILEが、サーバーのオペレーティング・システムのファイル・システム上に存在するかどうかを決定します。ゼロ以外の場合は、FILEEXISTは真、ゼロの場合は、偽です。 |
FILE LOBのみ |
PIC S9(9) COMP |
|
BFILEの名前。長さnは、1から255バイトです。実際の長さを使用します。 |
FILE LOBのみ |
PIC X(n) [VARYING] |
|
BFILEの場合は、入力BFILEロケータがOPEN文で使用されなかった場合は、このロケータからはOPENされていないものとみなされます。ただし、別のBFILEロケータによって、BFILEがOPENされていることもあります。複数のロケータを使用して、同一BFILE上で複数のOPENを実行することもできます。LOBの場合は、別のロケータを使用してLOBをオープンしても、LOBは入力ロケータによってOPENされているとみなされます。ゼロ以外の場合は、ISOPENは真、ゼロの場合は、偽です。 |
- |
PIC S9(9) COMP |
|
入力LOBロケータが一時LOBを参照するかどうかを決定します。ゼロ以外の場合は、ISTEMPORARYは真、ゼロの場合は、偽です。 |
BLOB、CLOBおよびNCLOBのみ |
PIC S9(9) COMP |
|
BLOBおよびBFILEの長さはバイト数単位、CLOBおよびNCLOBの長さは文字数単位で表されます。BFILEの場合、EOFが存在するときは、EOFも長さに含まれます。空の内部LOBは、ゼロ長になります。初期化されていないLOBおよびBFILEの長さは、定義されません。 |
- |
PIC 9(9) COMP |
使用上の注意
標識変数は、PIC S9(4) COMPとして宣言する必要があります。実行完了後、SQLERRD(3)には、エラーなしに取り出された属性の数が格納されます。実行エラーが発生した場合は、エラーが発生した属性の数はSQLERRD(3)の内容より1だけ多くなっています。
DESCRIBEの例
指定されたBFILEから、DIRECTORYおよびFILENAME属性を抽出する簡単なPro*COBOLの例です。
... 01 A-BFILE SQL-BFILE. 01 DIRECTORY PIC X(30) VARYING. 01 FILENAME PIC X(30) VARYING. 01 D-IND PIC S9(4) COMP. 01 F-IND PIC S9(4) COMP. 01 FEXISTS PIC S9(9) COMP. 01 ISOPN PIC S9(9) COMP. ...
最後に、いくつかのLOB表からBFILEロケータを選択し、DESCRIBEします。
EXEC SQL ALLOCATE :A-BFILE END-EXEC. EXEC SQL INSERT INTO lob_table (a_bfile) VALUES (BFILENAME ('lob.dir', 'image.gif')) END-EXEC. EXEC SQL SELECT a_bfile INTO :A-BFILE FROM lob_table WHERE ... END-EXEC. EXEC SQL DESCRIBE :A-BFILE GET DIRECTORY, FILENAME, FILEEXISTS, ISOPEN INTO :DIRECTORY:D-IND, :FILENAME:F-IND, FEXISTS, ISOPN ND-EXEC.
標識変数は、DIRECTORYおよびFILENAME属性を使用するときにのみ有効です。これらの属性は文字列なので、値が格納されるホスト変数バッファの大きさが不足している場合は、値が切り捨てられることがあります。切捨てが発生した場合は、インジケータの値には属性の元の長さが設定されます。
ポーリング・メソッドでREADを行うときの例です。
最初のLOB READで量にゼロを設定(または読み込まれる全データのサイズ量を設定)し、読込みポーリングを開始します。次の例では、この量にゼロが初期設定されます(詳細は省略してあります)。
EXEC SQL ALLOCATE :CLOB1 END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO END-OF-CLOB END-EXEC. EXEC SQL SELECT A_CLOB INTO :CLOB1 FROM LOB_TABLE WHERE ... END-EXEC. MOVE 0 TO AMT. EXEC SQL LOB READ :AMT FROM :VLOB1 AT :OFFSET INTO :BUFFER END-EXEC. READ-LOOP. EXEC SQL LOB READ :AMT FROM :CLOB1 INTO BUFFER $END-EXEC. GO TO READ-LOOP. END-OF-CLOB. EXEC SQL WHENEVER NOT FOUND CONTINUE END-EXEC. EXEC SQL FREE :CLOB1 END-EXEC.
次のコードは、バッファから内部CLOBへのデータの書込みの例です。初期書込み文のAMT (16文字)値は、書き込むデータ全体の長さと同じである必要があります。バッファの長さは5文字です。
初期読取りでEOFが読み取られた場合は、LOB WRITE ONEが行われます。EOFが読み込まれなかった場合は、バッファのLOB WRITE FIRSTによってポーリングが開始されます。データが読み込まれ、出力としてLOB WRITE NEXTが行われます。最後の書込みの後でデータが書き込まれるため、LOB WRITE NEXTにはオフセットは必要ありません。EOFが読み取られると、読取りループが終了し、LOB WRITE LASTが行われます。戻された量は、量の初期値(16)と等しくなっている必要があります。
MOVE 16 TO AMT. PERFORM READ-NEXT-RECORD. MOVE INREC TO BUFFER-ARR. MOVE 5 TO BUFFER-LEN. IF (END-OF-FILE = "Y") EXEC SQL LOB WRITE ONE :AMT FROM :BUFFER INTO CLOB1 AT :OFFSET END-EXEC. PERFORM DISPLAY-CLOB ELSE EXEC SQL LOB WRITE FIRST :AMT FROM :BUFFER INTO :CLOB1 AT :OFFSET END-EXEC. PERFORM READ-NEXT-RECORD. PERFORM WRITE-TO-CLOB UNTIL END-OF-FILE = "Y". MOVE INREC TO BUFFER-ARR. MOVE 1 TO BUFFER-LEN. EXEC SQL LOB WRITE LAST :AMT FROM :BUFFER INTO :CLOB1 END-EXEC. PERFORM DISPLAY-CLOB. ... WRITE-TO-CLOB. MOVE INREC TO BUFFER-ARR. MOVE 5 TO BUFFER-LEN. EXEC SQL LOB WRITE NEXT :AMT FROM :BUFFER INTO :CLOB1 END-EXEC. PERFORM READ-NEXT RECORD. READ-NEXT-RECORD. MOVE SPACES TO INREC. READ INFILE NEXT RECORD AT END MOVE "Y" TO END-OF-FILE. ...
プログラムLOBDEMO1.PCOは、いくつかのLOB埋込みSQL文の例です。ソース・コードは、demo
ディレクトリ内にあります。このアプリケーションでは、社会保障番号列、名前列および交通違反の集計が格納されているCLOB列で構成されるlicense_table
という表を使用します。標準的な自動車部門の簡単なSQL操作を、いくつかモデル化します。
発生する可能性のあるアクションを示します。
新しいレコードを追加します。
社会保障番号別のレコード・リストを出力します。
特定の社会保障番号で指定して、レコード情報のリストを出力します。
既存のCLOBの内容に新しい交通違反を追加します。
LOBDEMO1.PCOの内容は次のとおりです。
********************************************************************* * LOB Demo 1: DMV Database * * * * SCENARIO: * * * * We consider the example of a database used to store driver's * * licenses. The licenses are stored as rows of a table containing * * three columns: the sss number of a person, his/her name and the * * text summary of the info found in his license. * * * * The sss number and the name are the unique social security number * * and name of an individual. The text summary is a summary of the * * information on the individual, including his driving record, * * which can be arbitrarily long and may contain comments and data * * regarding the person's driving ability. * * * * APPLICATION OVERVIEW: * * * * This example demonstrate how a Pro*COBOL client can handle the * * new LOB datatypes. Demonstrated are the mechanisms for accessing * * and storing lobs to/from tables. * * * * To run the demo: * * * * 1. Execute the script, lobdemo1.sql in Server Manager * * 2. Precompile using Pro*COBOL * * procob lobdemo1 * * 3. Compile/Link (This step is platform specific) * * * * lobdemo1.sql contains the following SQL statements: * * * * connect scott/tiger; * * * * drop table license_table; * * * * create table license_table( * * sss char(9), * * name varchar2(50), * * txt_summary clob); * * * * insert into license_table * * values('971517006', 'Dennis Kernighan', * * 'Wearing a Bright Orange Shirt'); * * * * insert into license_table * * values('555001212', 'Eight H. Number', * * 'Driving Under the Influence'); * * * * insert into license_table * * values('010101010', 'P. Doughboy', * * 'Impersonating An Oracle Employee'); * * * * insert into license_table * * values('555377012', 'Calvin N. Hobbes', * * 'Driving Under the Influence'); * * * * The main program provides the menu of actions that can be * * performed. The program stops when the number 5 (Quit) option * * is entered. Depending on the input, this main program calls * * the appropriate nested program to execute the chosen action. * * * ********************************************************************* IDENTIFICATION DIVISION. PROGRAM-ID. LOBDEMO1. DATA DIVISION. WORKING-STORAGE SECTION. 01 USERNAME PIC X(5). 01 PASSWD PIC X(5). 01 CHOICE PIC 9 VALUE 0. 01 SSS PIC X(9). 01 SSSEXISTS PIC 9 VALUE ZERO. 01 LICENSE-TXT SQL-CLOB . 01 NEWCRIME PIC X(35) VARYING. 01 SSSCOUNT PIC S9(4) COMP. 01 THE-STRING PIC X(200) VARYING. 01 TXT-LENGTH PIC S9(9) COMP. 01 CRIMES. 05 FILLER PIC X(35) VALUE "Driving Under the Influence". 05 FILLER PIC X(35) VALUE "Grand Theft Auto". 05 FILLER PIC X(35) VALUE "Driving Without a License". 05 FILLER PIC X(35) VALUE "Impersonating an Oracle Employee". 05 FILLER PIC X(35) VALUE "Wearing a Bright Orange Shirt". 01 CRIMELIST REDEFINES CRIMES. 05 CRIME PIC X(35) OCCURS 5 TIMES. 01 CRIME-INDEX PIC 9. 01 TXT-LEN PIC S9(9) COMP. 01 CRIME-LEN PIC S9(9) COMP. 01 NAME1 PIC X(50) VARYING. 01 NEWNAME PIC X(50). ********************************************************************* EXEC SQL INCLUDE SQLCA END-EXEC. PROCEDURE DIVISION. A000-CONTROL SECTION. ********************************************************************* * A000-CONTROL * Overall control section ********************************************************************* A000-CNTRL. EXEC SQL WHENEVER SQLERROR DO PERFORM Z900-SQLERROR END-EXEC. PERFORM B000-LOGON. PERFORM C000-MAIN UNTIL CHOICE = 5. PERFORM D000-LOGOFF. A000-EXIT. STOP RUN. B000-LOGON SECTION. ********************************************************************* * B000-LOGON * Log on to database. ********************************************************************* B000-LGN. DISPLAY '**************************************************'. DISPLAY '* Welcome to the DMV Database *'. DISPLAY '**************************************************'. MOVE "scott" TO USERNAME. MOVE "tiger" TO PASSWD. EXEC SQL CONNECT :USERNAME IDENTIFIED BY :PASSWD END-EXEC. DISPLAY " ". DISPLAY "Connecting to license database account: ", USERNAME, "/", PASSWD. DISPLAY " ". B000-EXIT. EXIT. C000-MAIN SECTION. ********************************************************************* * C000-MAIN * Display the main menu and action requests ********************************************************************* C000-MN. DISPLAY " ". DISPLAY "License Options:". DISPLAY "1. List available records by SSS number". DISPLAY "2. Get information on a particular record". DISPLAY "3. Add crime to a record". DISPLAY "4. Insert new record to database". DISPLAY "5. Quit". DISPLAY " ". MOVE ZERO TO CHOICE. PERFORM Z300-ACCEPT-CHOICE UNTIL CHOICE < 6 AND CHOICE > 0. IF (CHOICE = 1) PERFORM C100-LIST-RECORDS. IF (CHOICE = 2) PERFORM C200-GET-RECORD. IF (CHOICE = 3) PERFORM C300-ADD-CRIME. IF (CHOICE = 4) PERFORM C400-NEW-RECORD. C000-EXIT. EXIT. C100-LIST-RECORDS SECTION. ********************************************************************* * C100-LIST-RECORDS * Select Social Security Numbers from LICENCSE_TABLE * and display the list ********************************************************************* C100-LST. EXEC SQL DECLARE SSS_CURSOR CURSOR FOR SELECT SSS FROM LICENSE_TABLE END-EXEC. EXEC SQL OPEN SSS_CURSOR END-EXEC. DISPLAY "Available records:". PERFORM C110-DISPLAY-RECORDS UNTIL SQLCODE = 1403. EXEC SQL CLOSE SSS_CURSOR END-EXEC. C100-EXIT. EXIT. C110-DISPLAY-RECORDS SECTION. ********************************************************************* * C110-DISPLAY-RECORDS * Fetch the next record from the cursor and display it. ********************************************************************* C110-DSPLY. EXEC SQL FETCH SSS_CURSOR INTO :SSS END-EXEC. IF SQLCODE = 0 THEN DISPLAY SSS. C110-EXIT. EXIT. C200-GET-RECORD SECTION. ******************************************************************* * C200-GET-RECORD * Allocates the global clob LICENSE-TXT then selects * the name and text which corresponds to the client-supplied * sss. It then calls Z200-PRINTCRIME to print the information and * frees the clob. ******************************************************************* C200-GTRECRD. PERFORM Z100-GET-SSS. IF (SSSEXISTS = 1) EXEC SQL ALLOCATE :LICENSE-TXT END-EXEC EXEC SQL SELECT NAME, TXT_SUMMARY INTO :NAME1, :LICENSE-TXT FROM LICENSE_TABLE WHERE SSS = :SSS END-EXEC DISPLAY "================================================== - "========================" DISPLAY " " DISPLAY "NAME: ", NAME1-ARR, "SSS: ", SSS DISPLAY " " PERFORM Z200-PRINTCRIME DISPLAY " " DISPLAY "================================================== - "========================" EXEC SQL FREE :LICENSE-TXT END-EXEC ELSE DISPLAY "SSS Number Not Found". C200-EXIT. EXIT. C310-GETNEWCRIME SECTION. ******************************************************************* * C310-GETNEWCRIME * Provides a list of the possible crimes to the user and * stores the user's correct response in the variable * NEWCRIME. ******************************************************************* C310-GTNWCRM. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "Select from the following:". PERFORM C311-DISPLAY-CRIME VARYING CRIME-INDEX FROM 1 BY 1 UNTIL CRIME-INDEX > 5. MOVE ZERO TO CHOICE. PERFORM Z300-ACCEPT-CHOICE UNTIL CHOICE < 6 AND CHOICE > 0. MOVE CRIME(CHOICE) TO NEWCRIME-ARR. MOVE 35 TO NEWCRIME-LEN. MOVE ZERO TO CHOICE. C310-EXIT. EXIT. C311-DISPLAY-CRIME SECTION. ******************************************************************* * C311-DISPLAY-CRIME * Display an element of the crime table ******************************************************************* C311-DSPLYCRM. DISPLAY "(", CRIME-INDEX, ") ", CRIME(CRIME-INDEX). C311-EXIT. EXIT. C320-APPENDTOCLOB SECTION. ******************************************************************* * C320-APPENDTOCLOB * Obtains the length of the global clob LICENSE-TXT and * uses that in the LOB WRITE statement to append the NEWCRIME * character buffer to the global clob LICENSE-TXT. * The name corresponding the global SSS is then selected * and displayed to the screen along with value of LICENSE-TXT. * The caller to this function must allocate, select and later * free the global clob LICENSE-TXT. ******************************************************************* C320-PPNDTCLB. EXEC SQL WHENEVER SQLERROR DO PERFORM Z900-SQLERROR END-EXEC. EXEC SQL LOB DESCRIBE :LICENSE-TXT GET LENGTH INTO :TXT-LEN END-EXEC. MOVE NEWCRIME-LEN TO CRIME-LEN. IF (TXT-LEN NOT = 0) ADD 3 TO TXT-LEN ELSE ADD 1 TO TXT-LEN. EXEC SQL LOB WRITE :CRIME-LEN FROM :NEWCRIME INTO :LICENSE-TXT AT :TXT-LEN END-EXEC. EXEC SQL SELECT NAME INTO :NAME1 FROM LICENSE_TABLE WHERE SSS = :SSS END-EXEC. DISPLAY " ". DISPLAY "NAME: ", NAME1-ARR, "SSS: ", SSS. DISPLAY " ". PERFORM Z200-PRINTCRIME. DISPLAY " ". C320-EXIT. EXIT. C300-ADD-CRIME SECTION. ******************************************************************* * ADD-CRIME * Obtains a sss and crime from the user and appends * the crime to the list of crimes of the corresponding sss. ******************************************************************* C300-DDCRM. EXEC SQL WHENEVER SQLERROR DO PERFORM Z900-SQLERROR END-EXEC. PERFORM Z100-GET-SSS. IF (SSSEXISTS = 1) EXEC SQL ALLOCATE :LICENSE-TXT END-EXEC PERFORM C310-GETNEWCRIME EXEC SQL SELECT TXT_SUMMARY INTO :LICENSE-TXT FROM LICENSE_TABLE WHERE SSS = :SSS FOR UPDATE END-EXEC PERFORM C320-APPENDTOCLOB EXEC SQL FREE :LICENSE-TXT END-EXEC ELSE DISPLAY "SSS Number Not Found". C300-EXIT. EXIT. C400-NEW-RECORD SECTION. ******************************************************************* * C400-NEW-RECORD * Obtains the sss and name of a new record and inserts them * along with an empty_clob() for the clob in the table. ******************************************************************* C400-NWRCRD. PERFORM Z100-GET-SSS. IF (SSSEXISTS = 1) DISPLAY "Record with that sss number already exists" ELSE DISPLAY "Name? " WITH NO ADVANCING ACCEPT NEWNAME DISPLAY " ". EXEC SQL ALLOCATE :LICENSE-TXT END-EXEC EXEC SQL INSERT INTO LICENSE_TABLE VALUES (:SSS, :NEWNAME, EMPTY_CLOB()) END-EXEC EXEC SQL SELECT TXT_SUMMARY INTO :LICENSE-TXT FROM LICENSE_TABLE WHERE SSS = :SSS END-EXEC DISPLAY "================================================== - "========================" DISPLAY "NAME: ", NEWNAME,"SSS: ", SSS PERFORM Z200-PRINTCRIME DISPLAY "================================================== - "========================" EXEC SQL FREE :LICENSE-TXT END-EXEC. C400-EXIT. EXIT. D000-LOGOFF SECTION. ******************************************************************* * D000-LOGOFF * Commit the work done to the database and log off ******************************************************************* D000-LGFF. EXEC SQL COMMIT WORK RELEASE END-EXEC. DISPLAY " ". DISPLAY "HAVE A GOOD DAY!". DISPLAY " ". D000-EXIT. STOP RUN. Z100-GET-SSS SECTION. ******************************************************************* * Z100-GET-SSS * Fills the global variable SSS with the client-supplied sss. * Sets the global variable SSSEXISTS to 0 if the sss does not * correspond to any entry in the database, else sets it to 1. ******************************************************************* Z100-GTSSS. DISPLAY "Social Security Number? " WITH NO ADVANCING. ACCEPT SSS. DISPLAY " ". EXEC SQL SELECT COUNT(*) INTO :SSSCOUNT FROM LICENSE_TABLE WHERE SSS = :SSS END-EXEC. IF (SSSCOUNT = 0) MOVE 0 TO SSSEXISTS ELSE MOVE 1 TO SSSEXISTS. Z100-EXIT. EXIT. Z200-PRINTCRIME SECTION. ******************************************************************* * Z200-PRINTCRIME * Obtains the length of the global clob LICENSE-TXT and * uses that in the LOB READ statement to read the clob * into a character buffer to display the contents of the clob. * The caller to this function must allocate, select and later * free the global clob LICENSE-TXT. ******************************************************************* Z200-PRNTCRM. DISPLAY "=====================". DISPLAY " CRIME SHEET SUMMARY ". DISPLAY "=====================". MOVE SPACE TO THE-STRING-ARR. EXEC SQL LOB DESCRIBE :LICENSE-TXT GET LENGTH INTO :TXT-LENGTH END-EXEC. IF (TXT-LENGTH = 0) DISPLAY "Record is clean" ELSE EXEC SQL LOB READ :TXT-LENGTH FROM :LICENSE-TXT INTO :THE-STRING END-EXEC DISPLAY THE-STRING-ARR. Z200-EXIT. EXIT. Z300-ACCEPT-CHOICE SECTION. ******************************************************************* * Z300-ACCEPT-CHOICE * Accept a choice between 1 and 5 ******************************************************************* Z300-CCPT. DISPLAY "Your Selection (1-5)? " WITH NO ADVANCING. ACCEPT CHOICE. DISPLAY " ". IF CHOICE >5 OR CHOICE < 1 THEN DISPLAY "Invalid Selection" DISPLAY "Please Choose from the indicated list". Z300-EXIT. EXIT. Z900-SQLERROR SECTION. ******************************************************************* * Z900-SQLERROR * Called whenever a SQLERROR occurs. * Display the Error, Roll Back any work done and Log Off ******************************************************************* Z900-SQLRRR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. Z900-EXIT. STOP RUN.