この付録では、Oralceプリコンパイラ、リリース1.8の改良点と新機能について説明します。プロのソフトウェア開発者の実際的なニーズを満たすように設計されたこれらの機能は、効率的かつ信頼できるアプリケーションの作成に役立ちます。
Oracleプリコンパイラのリリース1.5、1.6および1.7では、インジケータ変数が関連付けられていないホスト変数にデータをFETCH
するソース・ファイルの場合、実行時にホスト変数にNULL
が戻されると、ORA-01405
のメッセージが表示されます。リリース1.8では、MODE=ORACLE
およびDBMS=V7
を指定するとき、UNSAFE_NULL=YES
も指定すると、ORA-01405
のメッセージが表示されなくなります。
Oracleデータベース用のアプリケーションを開発する場合、NULL
が戻される可能性のあるホスト変数には、インジケータ変数を組み込むことをお薦めします。ただし、Oracleバージョン6からOracleデータベース・バージョン7へアプリケーションを移行する際には、UNSAFE_NULL
オプションを使用すると、移行のプロセスが非常に容易になります。
詳細は、「UNSAFE_NULL」および「インジケータ変数の使用方法」を参照してください。
DBMS=V6
を指定してプリコンパイルしたアプリケーションは、Oracleバージョン6との完全な互換性が維持されます。Oracleデータベース・バージョン7にアップグレードするとき、DBMS=V6
を指定してプリコンパイルすると、アプリケーションはORA-01405
メッセージの影響を受けなくなります。
MODE=ORACLE
およびDBMS=V7
を指定してプリコンパイルしたアプリケーションでは、実行時にインジケータ変数が関係付けられていないホスト変数にNULL
が戻されると、ORA-01405
エラーが発生します。これらのオプションを指定してOracleデータベース・バージョン7にアップグレードするときには、次の2つの方法のいずれかでアプリケーションを移行する必要があります。
必要なインジケータ変数を組み込むようにソース・コードを変更
コマンドラインでUNSAFE_NULL=YES
を指定
Oracleデータベース・バージョン7にアップグレード中で、プリコンパイル時にDBMS=V7
を使用するとき、またはOracleバージョン6と異なるOracleデータベース・バージョン7の新機能を使用するとき、ほとんどの場合、ソース・ファイルに対する変更は最小限で済みます。ただし、アプリケーションでインジケータ変数が関連付けられていないホスト変数にNULL値をFETCH
する可能性がある場合は、ORA-01405
メッセージが表示されないようにUNSAFE_NULL
=YES
を指定し、ソース・ファイルに関連するインジケータ変数を追加しないでください。
DB2プリコンパイラの配列INSERTおよび配列SELECT構文が、Oracleプリコンパイラでサポートされるようになりました。オプションのROWSET句およびROWSET STARTING AT句は、フェッチ方向(FIRST、PRIOR、NEXT、LAST、CURRENT、RELATIVEおよびABSOLUTE)で使用されます。新しいINSERT/SELECT構文の詳細は、『Pro*COBOLプログラマーズ・ガイド』および『Pro*C/C++プログラマーズ・ガイド』を参照してください。
SQL規格により、規格に準拠するすべてのソフトウェア製品で、SQLアプリケーションを移植できます。Oracle機能は、ANSI/ISO SQL99規格(ANSI準拠の結合を含む)に準拠しています。Pro*Cobolでは、OracleデータベースでサポートされているすべてのSQL99機能がサポートされており、SELECT文、INSERT文、DELETE文およびUPDATE文と、DECLARE CURSOR文でのカーソル本体のSQL99構文がサポートされています。
Pro*C/C++またはPro*Cobol開発環境で使用されるSQLの実行計画を修正するには、プリコンパイル時にOracleのアウトライン機能を使用する必要があります。アウトラインは、SQL文と関連付けられた一連のオプティマイザのヒントとして実装されています。文に対するアウトラインの使用を有効にすると、Oracleでは格納されたヒントを自動的に検討し、それらのヒントに従って実行計画の生成を試みます。このようにして、異なる環境へのモジュールの統合やデプロイを行うときに、パフォーマンスに影響が及ばないようにすることができます。
Pro*C/C++およびPro*Cobolでアウトラインを作成するときには、次のSQL文を使用できます。
SELECT
DELETE
UPDATE
INSERT... SELECT
CREATE TABLE... AS SELECT
アウトライン・オプションが設定されると、プリコンパイラでは、正常にプリコンパイルが終了した時点でSQLファイルとLOGファイルの2つのファイルが生成されます。コマンドライン・オプションのoutline
およびoutlnprefix
が、アウトラインの生成を制御します。生成される各アウトラインの名前は一意です。アプリケーションで使用されるファイル名は一意であるため、この情報がアウトライン名の生成で使用されます。さらに、カテゴリ名も前に付けられます。
注意: Oracleでは、アウトライン名に30バイトしか指定できません。この制限を超えると、プリコンパイラではエラーが発生します。アウトライン名の長さは、outlnprefix オプションを使用すれば制限できます。 |
参照:
|
パフォーマンス向上のために、アプリケーション開発者は、埋込みSQL文内のホスト配列を参照できます。これにより、データベースへの1回のラウンドトリップで、SQL文の配列を実行できます。配列の実行によりパフォーマンスが大幅に向上するにもかかわらず、ANSI規格ではないという理由で、この機能を使用しない開発者もいます。たとえば、Oracleで配列実行を利用するために作成されたアプリケーションは、IBMのプリコンパイラではプリコンパイルできません。
回避策の1つは、バッファ済のINSERT文を使用することです。これにより、ANSI規格の埋込みSQL構文を保持しつつ、パフォーマンスを向上させることができます。
コマンドライン・オプションmax_row_insertは、INSERT文を実行する前にバッファされる行数を制御します。デフォルトはゼロで、機能は無効です。この機能を有効にするには、ゼロより大きい数を指定してください。
参照: 暗黙的バッファ挿入機能の使用方法の詳細は、次のマニュアルを参照してください。
|
文のキャッシングとは、セッションごとに文のキャッシュを提供し管理する機能のことです。サーバーでは、文を再び解析することなく、カーソルがいつでも使用できるようになっていることを意味します。文のキャッシングは、プリコンパイラ・アプリケーションで有効にでき、動的SQL文に依存するすべてのアプリケーションのパフォーマンス向上に役立ちます。パフォーマンスの向上は、動的文を再利用する際の解析のオーバーヘッドをなくすことで達成されます。
このパフォーマンスの改善は、動的文のキャッシングが可能になる新しいコマンドライン・オプションstmt_cache
(文のキャッシュ・サイズ用)を使用することで実現します。この新しいオプションを有効にすると、セッション作成時に文のキャッシュが作成されます。キャッシングは動的文に対してのみ適用され、静的文用のカーソル・キャッシュとこの機能は共存します。
コマンドライン・オプションのstmt_cache
には、0~65535の範囲の任意の値を指定できます。文のキャッシングは、デフォルトでは無効です(0の値)。stmt_cache
オプションは、アプリケーションで予想される数の個別の動的SQL文を保存するために設定できます。
例A-1 stmt_cacheオプションの使用方法
この例は、stmt_cache
オプションの使用方法を示しています。このプログラムでは、表に行を挿入し、ループでカーソルを使用して挿入した行を選択します。このプログラムのプリコンパイルにstmt_cacheオプションを使用すると、通常のプリコンパイルに比べてパフォーマンスが向上します。
/* * stmtcache.pc * * NOTE: * When this program is used to measure the performance with and without * stmt_cache option, do the following changes in the program, * 1. Increase ROWSCNT to high value, say 10000. * 2. Remove all the print statements, usually which comsumes significant * portion of the total program execution time. * * HINT: In Linux, gettimeofday() can be used to measure time. */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sqlca.h> #include <oraca.h> #define ROWSCNT 10 char *username = "scott"; char *password = "tiger"; /* Function prototypes */ void sql_error(char *msg); void selectdata(); void insertdata(); int main() { EXEC SQL WHENEVER SQLERROR DO sql_error("Oracle error"); /* Connect using the default schema scott/tiger */ EXEC SQL CONNECT :username IDENTIFIED BY :password; /* core functions to insert and select the data */ insertdata(); selectdata(); /* Rollback pll the changes and disconnect from Oracle. */ EXEC SQL ROLLBACK WORK RELEASE; exit(0); } /*Insert the data for ROWSCNT items into tpc2sc01 */ void insertdata() { varchar dynstmt[80]; int i; varchar ename[10]; float comm; char *str; /* Allocates temporary buffer */ str = (char *)malloc (11 * sizeof(char)); strcpy ((char *)dynstmt.arr, "INSERT INTO bonus (ename, comm) VALUES (:ename, :comm)"); dynstmt.len = strlen(dynstmt.arr); EXEC SQL PREPARE S FROM :dynstmt; printf ("Inserts %d rows into bonus table using dynamic SQL statement\n", ROWSCNT); for (i=1; i<=ROWSCNT; i++) { sprintf (str, "EMP_%05d",i); strcpy (ename.arr, str); comm = i; ename.len = strlen (ename.arr); EXEC SQL EXECUTE S USING :ename, :comm; } free(str); } /* Select the data using the cursor */ void selectdata() { varchar dynstmt[80]; varchar ename[10]; float comm; int i; strcpy((char *)dynstmt.arr, "SELECT ename, comm FROM bonus WHERE comm = :v1"); dynstmt.len = (unsigned short)strlen((char *)dynstmt.arr); printf ("Fetches the inserted rows using using dynamic SQL statement\n\n"); printf (" ENAME COMMISSION\n\n"); for (i=1; i<=ROWSCNT; i++) { /* Do the prepare in the loop so that the advantage of stmt_caching is visible*/ EXEC SQL PREPARE S FROM :dynstmt; EXEC SQL DECLARE C CURSOR FOR S; EXEC SQL OPEN C USING :i; EXEC SQL WHENEVER NOT FOUND DO break; /* Loop until the NOT FOUND condition is detected. */ for (;;) { EXEC SQL FETCH C INTO :ename, :comm; ename.arr[ename.len] = '\0'; printf ("%10s %7.2f\n", ename.arr, comm); } /* Close the cursor so that the reparsing is not required for stmt_cache */ EXEC SQL CLOSE C; } } void sql_error(char *msg) { printf("\n%s", msg); sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0'; oraca.orastxt.orastxtc[oraca.orastxt.orastxtl] = '\0'; oraca.orasfnm.orasfnmc[oraca.orasfnm.orasfnml] = '\0'; printf("\n%s\n", sqlca.sqlerrm.sqlerrmc); printf("in \"%s...\"\n", oraca.orastxt.orastxtc); printf("on line %d of %s.\n\n", oraca.oraslnr, oraca.orasfnm.orasfnmc); /* Disable ORACLE error checking to avoid an infinite loop * should another error occur within this routine. */ EXEC SQL WHENEVER SQLERROR CONTINUE; /* Release resources associated with the cursor. */ EXEC SQL CLOSE C; /* Roll back any pending changes and disconnect from Oracle. */ EXEC SQL ROLLBACK WORK RELEASE; exit(1); }
スクロール可能なカーソルとは、OracleでSQL文を実行し、実行中に処理した情報を格納する作業領域です。カーソルを実行すると、問合せの結果が結果セットと呼ばれる一連の行に格納されます。結果セットは、順次または非順次のいずれでもフェッチできます。非順次の結果セットは、スクロール可能カーソルと呼ばれます。スクロール可能カーソルにより、ユーザーはデータベース結果セットの行に、前方、後方、無作為のいずれの方法でもアクセスできます。このスクロール可能カーソルを使用すれば、プログラムでは結果セットの任意の行をフェッチできます。スクロール可能カーソルの詳細は、『Pro*COBOLプログラマーズ・ガイド』を参照してください。
Oracleで格納されるユニコード・データ(UTF16)は、常にビッグエンディアン方式です。現在、クライアント・アプリケーションは様々なプラットフォーム上で実行されます。LinuxおよびWindowsではリトルエンディアン方式で表わされ、Solarisではビッグエンティアン方式で表わされます。UTF16データが挿入または選択されるとき、Pro*Cobolではサーバーとクライアント間でエンディアン方式を変換しません。これは、PIC N変数でのUTF16(UCS2)文字列の破損の原因になります。
PIC N変数でのプラットフォーム・エンディアン(LinuxおよびWindowsの場合はリトルエンディアン方式、Solarisの場合はビッグエンディアン方式)は、コマンドライン・オプションのpicn_endian
を使用すれば維持できます。
新しいコマンドライン・オプション
picn_endian={BIG|OS}
picn_endian=bigの場合、PIC N変数は、キャラクタ・セットID AL16UTF16に関連付けられます。
picn_endian=osの場合、PIC N変数はキャラクタ・セットID UCS2に関連付けられます。
このオプションのデフォルト値は、現行の動作を維持するBIGです。このオプションは、NLS_NCHARがAL16UTF16でない場合は無視されます。
PIC N変数のキャラクタ・セットの方式は、既存のPro*Cobolコマンドライン・オプションを使用すれば設定できます。
charset_picn={nchar_charset|db_charset}
Pro*CobolプログラムのB領域の長さは、書式がANSIに設定されている場合、72に制限されます。Cobolコンパイラでは、最大253までのB領域の長さをサポートできるようになりました。これにより、プログラマは72列より長い行を自由に入力できます。Pro*Cobolでは、Pro*Cobolアプリケーションが最大253までの長さのB領域がサポートされるようになりました。それには、
FORMAT=VARIABLE
オプションを使用します。