A 新機能
この付録では、Oracleプリコンパイラ、リリース1.8の改良点と新機能について説明します。プロのソフトウェア開発者の実際的なニーズを満たすように設計されたこれらの機能は、効率的かつ信頼できるアプリケーションの作成に役立ちます。
A.1 インジケータ変数を使用しないNULLのフェッチについて
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およびインジケータ変数の使用についてを参照してください。
A.1.1 DBMS=V7およびMODE=ORACLEの使用方法について
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
を指定し、ソース・ファイルに関連するインジケータ変数を追加しないでください。
A.2 配列INSERTおよび配列SELECT構文の追加
DB2プリコンパイラの配列INSERTおよび配列SELECT構文が、Oracleプリコンパイラでサポートされるようになりました。オプションでROWSET句とROWSET STARTING AT句がフェッチの方向(FIRST, PRIOR, NEXT, LAST, CURRENT, RELATIVEおよびABSOLUTE)で使用されます。新しいINSERT/SELECT構文の詳細は、『Pro*COBOLプログラマーズ・ガイド』および『Pro*C/C++プログラマーズ・ガイド』を参照してください。
A.3 SQL99構文サポート
SQL規格により、規格に準拠するすべてのソフトウェア製品で、SQLアプリケーションを移植できます。Oracle機能は、ANSI/ISO SQL99規格(ANSI準拠の結合を含む)に準拠しています。Pro*Cobolでは、Oracle DatabaseでサポートされているすべてのSQL99機能がサポートされており、SELECT文、INSERT文、DELETE文およびUPDATE文と、DECLARE CURSOR文でのカーソル本体のSQL99構文がサポートされています。
A.4 実行計画の修正について
Pro*C/C++またはPro*Cobol開発環境で使用されるSQLの実行計画を修正するには、プリコンパイル時にOracleのアウトライン機能を使用する必要があります。アウトラインは、SQL文と関連付けられた一連のオプティマイザ・ヒントとして実装されます。SQL文のアウトラインの使用を有効にすると、Oracleでは、格納されたヒントが自動的に考慮され、それらのヒントに従って実行計画を生成しようとします。これにより、モジュールの統合時および異なる環境へのデプロイ時に、パフォーマンスは影響を受けません。
Pro*C/C++およびPro*Cobolでアウトラインを作成するときには、次のSQL文を使用できます。
-
SELECT
-
DELETE
-
UPDATE
-
INSERT... SELECT
-
CREATE TABLE... AS SELECT
アウトライン・オプションが設定されている場合、プリコンパイルが正常に終了すると、2つのファイル(SQLファイルおよびLOGファイル)が生成されます。コマンドライン・オプションoutline
およびoutlnprefix
は、アウトラインの生成を制御します。生成された各アウトライン名は一意です。アプリケーションで使用するファイル名が一意であるため、アウトライン名の生成時にこの情報が使用されます。また、カテゴリ名も接頭辞として使用されます。
注意:
アウトライン名の最大長は30バイトです。この制限を超えると、プリコンパイラではエラーが発生します。outlnprefix
オプションを使用すると、アウトライン名の長さを制限できます。
A.5 暗黙的バッファ挿入の使用について
パフォーマンス向上のために、アプリケーション開発者は、埋込みSQL文内のホスト配列を参照できます。これにより、データベースへの1回のラウンドトリップでSQL文の配列を実行できます。配列の実行によってパフォーマンスが大幅に向上するにもかかわらず、ANSI規格ではないため、この機能を使用しない開発者もいます。たとえば、Oracle製品で配列の実行を使用するように記述されたアプリケーションは、IBMのプリコンパイラを使用してプリコンパイルすることはできません。
対処方法として、バッファ済INSERT文を使用すると、ANSI規格の埋込みSQL構文を保持しながらパフォーマンスを向上させることができます。
コマンドライン・オプション「max_row_insert」は、INSERT文の実行前にバッファする行の数を制御します。このオプションのデフォルトは0で、機能は無効化されています。この機能を有効化するには、0よりも大きい任意の数を指定します。
A.6 動的SQL文のキャッシュ
文キャッシュは、セッションごとの文のキャッシュを提供および管理する機能です。サーバーでは、文を再び解析することなく、カーソルがいつでも使用できるようになっていることを意味します。文のキャッシングは、プリコンパイラ・アプリケーションで有効にでき、動的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 = "aaaaa"; char *password = "bbbbb"; /* 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 aaaaa/bbbbb */ 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); }
A.7スクロール可能なカーソル
スクロール可能カーソルは、SQL文が実行され、実行中に処理された情報が格納される作業領域です。カーソルを実行すると、問合せの結果は結果セットと呼ばれる一連の行に配置されます。結果セットは、順番にフェッチすることも、順不同でフェッチすることもできます。順不同の結果セットをスクロール可能カーソルと呼びます。スクロール可能カーソルを使用すると、ユーザーは前から、後ろからまたはランダムな方法でデータベース結果セットの行にアクセスできます。このスクロール可能なカーソルにより、プログラムは結果セットの任意の行をフェッチできます。スクロール可能なカーソルの詳細は、「スクロール可能なカーソル」を参照してください。
A.8 プラットフォームのエンディアン形式のサポート
Oracleで格納されるユニコード・データ(UTF16)は、常にビッグエンディアン方式です。現在、クライアント・アプリケーションは様々なプラットフォームで実行されます。LinuxおよびWindowsではリトルエンディアン方式で表され、Solarisではビッグエンティアン方式で表されます。Pro*Cobolでは、UTF16のデータが挿入または選択されると、サーバーとクライアント間のエンディアン形式が変換されません。このため、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}