Oracleプリコンパイラでは、SQL*Netを介して分散処理がサポートされます。アプリケーションは、ローカル・データベースおよびリモート・データベースの任意の組合せに同時にアクセスしたり、同じデータベースへの複数の接続を確立できます。図3-2では、アプリケーション・プログラムが1つのローカルOracleデータベースおよび3つのリモートOracleデータベースと通信しています。ORA2、ORA3およびORA4は、CONNECT文で使用される論理名です。
SQL*Netは、ネットワーク上の異なるマシン間およびオペレーティング・システム間に存在する境界を排除することによって、Oracleのツール製品に分散処理環境を提供します。この項では、SQL*Netを介した分散処理がOracleプリコンパイラでどのようにサポートされているかを説明します。さらに、アプリケーションで次の処理がどのように行われるかも学習します。
他のデータベースへの直接または間接アクセス
ローカルおよびリモート・データベースの任意の組合せへの同時アクセス
同じデータベースへの複数接続
ネットワーク上の通信ポイントは、ノードと呼ばれます。SQL*Netにより、ネットワーク上のノード間で情報(SQL文、データおよびステータス・コード)を送信できます。
プロトコルは、ネットワークへのアクセスに関する一連の規則です。この規則では、障害発生後のリカバリ手順、データを送信およびエラー検査の形式などが規定されます。
ローカル・ドメイン内のデフォルトのデータベースに接続するためのSQL*Netの構文で使用するのは、そのデータベースのサービス名のみです。
サービス名がデフォルト(ローカル)・ドメイン内にない場合は、グローバル指定(すべてのドメインの指定)を使用する必要があります。次に例を示します。
HR.US.ORACLE.COM
各ノードにはデフォルトのデータベースがあります。CONNECT
文でノードを指定し、データベースを指定しない場合、指定したローカルまたはリモート・ノード上のデフォルトのデータベースに接続されます。データベースもノードも指定しない場合は、現在のノード上のデフォルト・データベースに接続されます。CONNECT
文でデフォルト・データベースと現在のノードを指定することはできますが、必要ありません。
デフォルトの接続は、AT句のないCONNECT
文を使用して行われます。ローカルまたはリモートの任意のノード上のデフォルトまたは非デフォルトの任意のデータベースに接続できます。AT句のないSQL文は、デフォルトの接続に対して実行されます。逆に、非デフォルトの接続は、AT句があるCONNECT
文により行われます。AT句があるSQL文は、非デフォルトの接続に対して実行されます。
すべてのデータベース名は一意である必要があります。ただし、2つ以上のデータベース名で同じ接続を指定できます。つまり、任意のノード上で、任意のデータベースに対する複数の接続を持てます。
EXEC SQL CONNECT :userid IDENTIFIED BY :password
または、次の文でも接続できます。
EXEC SQL CONNECT :usr_pwd;
usr_pwdには、username/passwordが含まれます。
次のようにして自動的に接続することもできます。データベースおよびノードを指定しない場合、現在のノード上のデフォルトのデータベースに接続されます。別のデータベースに接続する場合は、そのデータベースを明示的に指定する必要があります。
明示的接続では、SQL文で参照される接続名を指定して、別のデータベースに直接接続します。同時に複数のデータベースに接続することも、同じデータベースに複数回接続することもできます。
次の例では、リモート・ノードにある1つの非デフォルト・データベースに接続します。
注意:
この機能を簡単に説明するために、この例では、デプロイされたシステムで通常使用されるパスワード管理手法を実行していません。本番環境では、Oracle Databaseのパスワード管理ガイドラインに従って、サンプル・アカウントを無効にします。パスワード管理ガイドラインおよび他のセキュリティに関する推奨事項については、『Oracle Databaseセキュリティ・ガイド』を参照してください。
-- Declare necessary host variables.
EXEC SQL BEGIN DECLARE SECTION;
username CHARACTER(10);
password CHARACTER(10);
db_string CHARACTER(20);
EXEC SQL END DECLARE SECTION;
set username = 'scott';
set password = 'tiger';
set db_string = 'd:newyork-nondef';
-- Assign a unique name to the database connection.
EXEC SQL DECLARE db_name DATABASE;
-- Connect to the nondefault database
EXEC SQL CONNECT :username IDENTIFIED BY :password
AT db_name USING :db_string;
この例の識別子は、次の目的で使用されています。
ホスト変数usernameおよびpasswordは、有効なユーザーを識別します。
ホスト変数db_stringには、DECnetプロトコルを使用してリモート・ノードにある非デフォルトのデータベースに接続するためのSQL*Net構文が含まれています。
未宣言の識別子db_nameは、非デフォルト接続の名前を指定します。これは、Oracleで使用される識別子で、ホスト変数でもプログラム変数でもありません。
USING句では、db_nameに関連付けられるネットワーク、コンピュータおよびデータベースを指定します。その後、AT句(db_name付き)を使用したSQL文が、db_stringに指定したデータベースで実行されます。
もう1つの方法として、次の例に示すように、AT句で文字ホスト変数を使用できます。
EXEC SQL BEGIN DECLARE SECTION; username CHARACTER(10); password CHARACTER(10); db_name CHARACTER(10); db_string CHARACTER(20); EXEC SQL END DECLARE SECTION; set username = 'scott'; set password = 'tiger'; set db_name = 'oracle1'; set db_string = 'd:newyork-nondef'; -- connect to the nondefault database EXEC SQL CONNECT :username IDENTIFIED BY :password AT :db_name USING :db_string; ...
db_nameがホスト変数の場合、DECLARE DATABASE文は不要です。db_nameが未宣言の識別子である場合にのみ、CONNECT ... AT db_name文を実行する前に、DECLARE db_name DATABASE文を実行する必要があります。
SQLの操作。権限を付与されている場合は、非デフォルトの接続で任意のSQL DML文を実行できます。たとえば、次のように入力します。
EXEC SQL AT db_name SELECT ... EXEC SQL AT db_name INSERT ... EXEC SQL AT db_name UPDATE ...
次の例では、db_nameはホスト変数です。
EXEC SQL AT :db_name DELETE ...
db_nameがホスト変数の場合、SQL文で参照されるすべてのデータベース表を、DECLARE TABLE文で定義する必要があります。
カーソルの制御。OPEN, FETCHやCLOSEなどのカーソル制御文は例外で、AT句を使用しません。カーソルを明示的に指定したデータベースに関連付ける場合は、次のようにDECLARE CURSOR文でAT句を使用してください。
EXEC SQL AT :db_name DECLARE emp_cursor CURSOR FOR ... EXEC SQL OPEN emp_cursor ... EXEC SQL FETCH emp_cursor ... EXEC SQL CLOSE emp_cursor;
db_nameがホスト変数の場合、宣言されたカーソルを参照するすべてのSQL文の適用範囲内で宣言する必要があります。たとえば、あるサブプログラム内でカーソルをオープンし、別のサブプログラムでそのカーソルからフェッチする場合は、db_nameをグローバルに宣言するか、それを各サブプログラムに渡す必要があります。
カーソルからのオープン、クローズまたはフェッチには、AT句は使用しません。SQL文は、DECLARE CURSOR文のAT句で名前を付けられたデータベースか、カーソルの宣言でAT句が使用されていない場合はデフォルトのデータベースにおいて実行されます。
AT :host_variable句を使用すると、カーソルに関連付けられた接続を変更できます。ただし、カーソルがオープンされているときは対応付けを変更できません。次に例を示します。
EXEC SQL AT :db_name DECLARE emp_cursor CURSOR FOR ... set db_name = 'oracle1'; EXEC SQL OPEN emp_cursor; EXEC SQL FETCH emp_cursor INTO ... set db_name = 'oracle2'; EXEC SQL OPEN emp_cursor; -- illegal, cursor still open EXEC SQL FETCH emp_cursor INTO ...
これは不適切です。2番目のOPEN文を実行しようとしても、 emp_cursor がまだオープン状態であるためです。異なる接続に対して別々のカーソルが維持されることはありません。emp_cursorは1つのみ存在できます。別の接続のために再オープンするには、その前にクローズする必要があります。最後の例をデバッグするには、次のように、単にカーソルをクローズしてから再オープンします。
EXEC SQL CLOSE emp_cursor; -- close cursor first set db_name = 'oracle2'; EXEC SQL OPEN emp_cursor; EXEC SQL FETCH emp_cursor INTO ...
動的SQL。動的SQL文は、文中ではAT句が使用されないカーソル制御文に類似しています。動的SQL方法1では、非デフォルトの接続で文を実行する場合は、AT句を使用する必要があります。次に例を示します。
EXEC SQL AT :db_name EXECUTE IMMEDIATE :sql_stmt;
方法2、3および4では、非デフォルト接続で文を実行する場合、DECLARE STATEMENT文でのみAT句を使用します。PREPARE、DESCRIBE、OPEN、FETCHおよびCLOSEなど、その他の動的SQL文はAT句を使用しません。次の例は、方法2を示しています。
EXEC SQL AT :db_name DECLARE sql_stmt STATEMENT; EXEC SQL PREPARE sql_stmt FROM :sql_string; EXEC SQL EXECUTE sql_stmt;
次の例は方法3を示します。
EXEC SQL AT :db_name DECLARE sql_stmt STATEMENT; EXEC SQL PREPARE sql_stmt FROM :sql_string; EXEC SQL DECLARE emp_cursor CURSOR FOR sql_stmt; EXEC SQL OPEN emp_cursor ... EXEC SQL FETCH emp_cursor INTO ... EXEC SQL CLOSE emp_cursor;
複数の接続を同時にオープンする場合(アクティブな接続の識別にAT句が必要)でなければ、リモート・データベースに接続する際にAT句を使用する必要はありません。リモート・データベースにデフォルト接続を行うには、次の構文を使用します。
EXEC SQL CONNECT :username IDENTIFIED BY :password USING :db-string;
単一の明示的接続の場合と同様に、複数の明示的接続にもAT db_name句を使用できます。次の例では、2つの非デフォルト・データベースに同時に接続しています。
EXEC SQL BEGIN DECLARE SECTION; username CHARACTER(10); password CHARACTER(10); db_string1 CHARACTER(20); db_string2 CHARACTER(20); EXEC SQL END DECLARE SECTION; ... set username = 'scott'; set password = 'tiger'; set db_string1 = 'New_York'; set db_string2 = 'Boston'; -- give each database connection a unique name EXEC SQL DECLARE db_name1 DATABASE; EXEC SQL DECLARE db_name2 DATABASE; -- connect to the two nondefault databases EXEC SQL CONNECT :username IDENTIFIED BY :password AT db_name1 USING :db_string1; EXEC SQL CONNECT :username IDENTIFIED BY :password AT db_name2 USING :db_string2;
未宣言識別子db_name1およびdb_name2は、2つの非デフォルト・ノードにあるデフォルト・データベースの指名に使用され、これにより、SQL文では後からそれらのデータベースを名前で参照できます。
または、次の例のように、AT句でホスト変数を使用できます。
EXEC SQL BEGIN DECLARE SECTION; username CHARACTER(10); password CHARACTER(10); db_name CHARACTER(10); db_string CHARACTER(20); EXEC SQL END DECLARE SECTION; ... set username = 'scott'; set password = 'tiger'; FOR EACH nondefault database -- get next database name and SQL*Net string display 'Database Name? '; read db_name; display 'SQL*Net String? '; read db_string; -- connect to the nondefault database EXEC SQL CONNECT :username IDENTIFIED BY :password AT :db_name USING :db_string; ENDFOR;
この方法を使用すれば、次の例のように、同じデータベースに複数の接続を行うこともできます。
set username = 'scott'; set password = 'tiger'; set db_string = 'd:newyork-nondef'; FOR EACH nondefault database -- get next database name display 'Database Name? '; read db_name; -- connect to the nondefault database EXEC SQL CONNECT :username IDENTIFIED BY :password AT :db_name USING :db_string; ENDFOR;
複数の接続に同じSQL*Net文字列を使用する場合でも、接続ごとに異なるデータベース名を使用する必要があります。
次の例では、1つの非デフォルト・データベースに接続します。まず、プログラムでは次の文が実行され、データベース・リンクが定義されます(通常、データベース・リンクは、DBAまたはユーザーが対話形式で確立します)。
EXEC SQL CREATE DATABASE LINK db_link CONNECT TO username IDENTIFIED BY password USING 'd:newyork-nondef';
これにより、プログラムでは、次のようにデータベース・リンクを使用して、非デフォルトのEMP表に対して問合せを実行できます。
EXEC SQL SELECT ENAME, JOB INTO :emp_name, :job_title FROM emp@db_link WHERE DEPTNO = :dept_number;
データベース・リンクは、埋込みSQL文のAT句に使用されるデータベース名とは無関係です。単にOracleに非デフォルトのデータベースの位置、データベースへのパス、使用するOracleユーザー名およびパスワードを指示します。データベース・リンクは、明示的に削除されるまで、データベース・ディクショナリに格納されます。
例では、デフォルトのOracleサーバーは、データベース・リンクdb_linkを使用してSQL*Netで非デフォルトのデータベースに接続します。問合せはデフォルトのサーバーに送信されますが、非デフォルトのデータベースに転送されて実行されます。
データベース・リンクをさらに簡単に参照できるようにするには、次のようにシノニムを作成します(ここでも、通常は対話形式で行われます)。
EXEC SQL CREATE SYNONYM emp FOR emp@db_link;
その結果、プログラムで、次のように非デフォルトのEMP表に問合せができるようになります。
EXEC SQL SELECT ENAME, JOB INTO :emp_name, :job_title FROM emp WHERE DEPTNO = :dept_number;
次の例では、2つの非デフォルト・データベースに同時に接続します。まず、次の一連の文を実行し、2つのデータベース・リンクを定義して、2つのシノニムを作成します。
EXEC SQL CREATE DATABASE LINK db_link1 CONNECT TO username1 IDENTIFIED BY password1 USING 'd:newyork-nondef'; EXEC SQL CREATE DATABASE LINK db_link2 CONNECT TO username2 IDENTIFIED BY password2 USING 'd:chicago-nondef'; EXEC SQL CREATE SYNONYM emp FOR emp@db_link1; EXEC SQL CREATE SYNONYM dept FOR dept@db_link2;
その結果、プログラムで、次のように非デフォルトのEMP表とDEPT表に問合せができるようになります。
EXEC SQL SELECT ENAME, JOB, SAL, LOC FROM emp, dept WHERE emp.DEPTNO = dept.DEPTNO AND DEPTNO = :dept_number;
Oracleでは、db_link1にある非デフォルトのEMP表とdb_link2にある非デフォルトのDEPT表を結合することにより、問合せが実行されます。