この章では、Oracle Database Gatewayの主要な機能について説明します。この章の内容は、次のとおりです。
SQLとPL/SQLのサポート
異機種間レプリケーション
パススルーSQL
結果セットのサポート
データ・ディクショナリ変換
日時データ型
2フェーズ・コミット・プロトコル
ピース単位のLONGデータ型
SQL*PlusのDESCRIBEコマンド
分散環境におけるSQLの制約
異機種間サービスとOracleのオプティマイザの併用
注意: この章で説明する機能は、すべての異機種間サービスのゲートウェイで使用可能であるとはかぎりません。これらの機能に対する汎用サポート(異機種間サービスで提供)が必要であるのみでなく、そのドライバのサポートも追加する必要があります。ご使用のゲートウェイに特定の機能がサポートされているかどうかは、該当するゲートウェイのマニュアルを参照して判断してください。 |
SQL文の変換とデータ型のマッピングは、機能に基づいて実行されます。PL/SQLコールは、Oracle以外のシステムのストアド・プロシージャにマップされます。SQL文の場合、リモート・システムに機能がなければ、より単純な問合せが発行されるか、文が複数の問合せに分割され、必要な結果がOracleデータベースでの後処理により取得されます。
異機種間サービスでは、ほとんどの場合はOracle以外のシステムをOracle分散セッションに取り込むことができますが、これにはいくつかの制限があります。一般的な制限事項を次に示します。
SQL文のCONNECT BY
句に対するサポートはありません。
ROWID
のサポートは限定的です。詳細は、個々のゲートウェイのマニュアルを参照してください。異機種間サービスを使用するゲートウェイでは、OracleのユニバーサルROWID
データ型はサポートされません。
LOB、ユーザー定義型およびREFはサポートされません。
リモート・パッケージはサポートされません。
リモート・ストアド・プロシージャでは、REF CURSOR
型のout
引数は指定できますが、in
またはin-out
オブジェクトは使用できません。
Oracle異機種間サービス・エージェントでは、共有データベース・リンクはサポートされません。
注意: 各ゲートウェイには、前述の一般的な制限事項に加えて、付加的な制限事項が存在する場合があります。製品の制限事項の全リストは、個々のゲートウェイのマニュアルを参照してください。 |
Oracle以外のシステムとOracleサーバー間で、マテリアライズド・ビューを使用してデータをレプリケートできます。
マテリアライズド・ビューにより、Oracle以外のマスター・サイトにある表から特定の時点で取得されたデータがインスタンス化されます。この時点はリフレッシュ操作により定義されます。リフレッシュ操作により、このデータがOracleサーバーにコピーされ、Oracle上のコピーがOracle以外のシステム上のマスター・コピーと同期化されます。これにより、実体化されたデータがOracleサーバーでビューとして使用可能になります。
レプリケーション機能は、リフレッシュをスケジュールし、マテリアライズド・ビューを管理しやすいようにレプリケーション・グループに収集するためのメカニズムを提供します。リフレッシュ・グループにより、複数のマテリアライズド・ビューをシングル・オブジェクトと同様にリフレッシュできます。
異機種間レプリケーションのサポートは、必ずOracle間レプリケーション機能全体のサブセットに限定されます。
マスター・サイトとして使用できるのは、Oracle以外のシステムのみです。これは、マテリアライズド・ビューを作成できるのがOracleサーバーのみであるためです。
マテリアライズド・ビューでは、完全リフレッシュを使用する必要があります。これは、高速リフレッシュを使用するには、Oracle以外のシステムでOracle固有の機能が必要になるためです。
タイプによっては、Oracle以外のシステム上で表を参照する目的では作成できないマテリアライズド・ビューがあります。主キーと副問合せのマテリアライズド・ビューはサポートされますが、ROWID
とOBJECT ID
のマテリアライズド・ビューはサポートされません。これは、ROWID
の書式と内容についてはSQL規格がなく、Oracle以外のシステムにはOracleオブジェクトが実装されていないためです。
Oracleの異機種間サービス機能を介したOracle以外のデータへのアクセスには、その他の制限が適用されます。次に最も重要な制限事項を示します。
固定ビューにマップされる表列のOracle以外のデータ型には、Oracleデータ型との互換性(つまりマッピング)が必要です。通常、このことは、ANSI SQL規格により定義されたデータ型について該当します。
副問合せのマテリアライズド・ビューでは、Oracle以外の個々のシステムにより制限される言語機能を使用できない場合があります。多くの場合、異機種間サービスでは、Oracleサーバー内で問合せを処理することでこの種の言語機能がサポートされますが、Oracle以外のシステムには、異機種間サービスが問合せの実行を試みるまでは診断できない制限が課せられている場合があります。
次の例に、Oracle以外のシステムからOracleデータ・ストアにデータをレプリケートする3つのマテリアライズド・ビューの基本設定と使用例を示します。
注意: 次の例で、remote_db はOracleデータベース・サーバーからアクセスするOracle以外のシステムを指します。
これらの例を環境にあわせて変更してください。そのままの状態では実行しないでください。 |
例1: 異機種間レプリケーションに使用するマテリアライズド・ビューの作成
この例では、以降の例に使用する3つのマテリアライズド・ビューを作成します。
customer@remote_db
表の主キーのマテリアライズド・ビューを作成します。
CREATE MATERIALIZED VIEW pk_mv REFRESH COMPLETE AS SELECT * FROM customer@remote_db WHERE "zip" = 94555;
orders@remote_db
表およびcustomer@remote_db
表の副問合せのマテリアライズド・ビューを作成します。
CREATE MATERIALIZED VIEW sq_mv REFRESH COMPLETE AS SELECT * FROM orders@remote_db o WHERE EXISTS (SELECT c."c_id" FROM customer@remote_db c WHERE c."zip" = 94555 and c."c_id" = o."c_id" );
remote_db
上の複数の表からのデータの複合マテリアライズド・ビューを作成します。
CREATE MATERIALIZED VIEW cx_mv REFRESH COMPLETE AS SELECT c."c_id", o."o_id" FROM customer@remote_db c, orders@remote_db o, order_line@remote_db ol WHERE c."c_id" = o."c_id" AND o."o_id" = ol."o_id";
例2: 異機種間レプリケーションに使用するリフレッシュ・グループの設定
BEGIN dbms_refresh.make('refgroup1', 'pk_mv, sq_mv, cx_mv', NULL, NULL); END; /
例3: 3つのマテリアライズド・ビューすべての強制リフレッシュ
BEGIN dbms_refresh.refresh('refgroup1'); END; /
関連項目: マテリアライズド・ビューとレプリケーション機能の詳細は、『Oracle Databaseアドバンスト・レプリケーション』を参照してください。 |
パススルーSQL機能を使用すると、文をOracleサーバーで解析せずに直接Oracle以外のシステムに送ることができます。この機能は、Oracle以外のシステムでOracleに等価文のない文での操作が見込まれる場合に役立ちます。
この項の内容は、次のとおりです。
DBMS_HS_PASSTHROUGHパッケージの使用
パススルーSQLの使用による影響の検討
パススルーSQL文の実行
PL/SQLのDBMS_HS_PASSTHROUGH
パッケージを使用すると、Oracle以外のシステムで直接パススルーSQL文を実行できます。このパッケージで実行される文は、標準SQL文と同じトランザクションで実行されます。
DBMS_HS_PASSTHROUGH
パッケージは仮想パッケージです。概念上は、Oracle以外のシステムに常駐します。ただし、実際には、このパッケージのコールは異機種間サービスにより仲介され、1つ以上の異機種間サービス・コールにマップされます。次に、これらの異機種間サービス・コールは、ドライバによりOracle以外のシステムのAPIにマップされます。クライアント・アプリケーションは、Oracle以外のシステムのストアド・プロシージャをコールする場合と同じ方法で、データベース・リンクを介してパッケージ内のプロシージャをコールする必要があります。異機種間サービスにより実行される特殊処理は、ユーザーに対して透過的です。
関連項目: このパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。 |
Oracle以外のシステムでトランザクションを暗黙的にコミットまたはロールバックするパススルーSQL文を実行すると、そのトランザクションに影響します。たとえば、一部のシステムでは、データ定義言語(DDL)文を含むトランザクションが暗黙的にコミットされます。Oracleデータベース・サーバーは迂回されるため、Oracle以外のシステムでのコミットは認識されません。そのため、Oracleデータベース・サーバーではトランザクションがコミットされない間に、Oracle以外のシステムでデータがコミットされる可能性があります。
Oracleデータベース・サーバーでトランザクションがロールバックされると、Oracleデータベース・サーバーとOracle以外のサーバー間でデータに一貫性がなくなる可能性があります。このような状況では、グローバルなデータ非一貫性が発生します。
アプリケーションで通常のCOMMIT
文を実行すれば、Oracleデータベース・サーバーはOracle以外のシステムと分散トランザクションを調整できることに注意してください。パススルー機能を使用して実行される文は、分散トランザクションの一部となります。
次の表に、DBMS_HS_PASSTHROUGH
パッケージで提供されるファンクションとプロシージャを示します。これらを使用してパススルーSQL文を実行できます。
INSERT
UPDATE
DELETE
DDL
非問合せ文を実行するには、EXECUTE_IMMEDIATE
ファンクションを使用します。たとえば、データベース・リンクsalesdb
を使用してアクセスできるOracle以外のシステムでDDL文を実行するには、次のように実行します。
DECLARE num_rows INTEGER; BEGIN num_rows := DBMS_HS_PASSTHROUGH.EXECUTE_IMMEDIATE@salesdb ('CREATE TABLE dept1 (n SMALLINT, loc CHARACTER(10))'); END;
num_rows
変数には、実行の影響を受ける行数が割り当てられます。DDL文の場合は、0(ゼロ)が戻されます。EXECUTE_IMMEDIATE
では問合せを実行できず、バインド変数を使用できないことに注意してください。
バインド変数を使用すると、同じSQL文に様々な値を指定して複数回使用できるため、SQL文に必要な解析回数が減少します。たとえば、特定の表に4行挿入する必要がある場合は、SQL文を1回解析し、行ごとにバインドして実行できます。1つのSQL文に0個以上のバインド変数を使用できます。
バインド変数を使用してパススルーSQL文を実行する手順は、次のとおりです。
カーソルをオープンします。
Oracle以外のシステムでSQL文を解析します。
変数をバインドします。
Oracle以外のシステムでSQL文を実行します。
カーソルをクローズします。
図3-1に、バインド変数を使用した非問合せ実行のフロー図を示します。
文でバインド変数を指定する方法は、Oracle以外のシステムの構文により決定されます。たとえば、Oracleでは、先行コロンを使用してバインド変数を定義します。次に例を示します。
... UPDATE emp SET sal=sal*1.1 WHERE ename=:ename; ...
この文で、ename
はバインド変数です。Oracle以外のシステムでは、バインド変数の指定に疑問符が必要になる場合があります。次に例を示します。
... UPDATE emp SET sal=sal*1.1 WHERE ename= ?; ...
バインド変数の手順では、ホスト・プログラム変数(この場合はPL/SQL)をこれらの各バインド変数と位置的に関連付ける必要があります。たとえば、前述の文を実行するには、次のPL/SQLプログラムを使用します。
DECLARE c INTEGER; nr INTEGER; BEGIN c := DBMS_HS_PASSTHROUGH.OPEN_CURSOR@salesdb; DBMS_HS_PASSTHROUGH.PARSE@salesdb(c, 'UPDATE emp SET SAL=SAL*1.1 WHERE ename=?'); DBMS_HS_PASSTHROUGH.BIND_VARIABLE@salesdb(c,1,'JONES'); nr:=DBMS_HS_PASSTHROUGH.EXECUTE_NON_QUERY@salesdb(c); DBMS_OUTPUT.PUT_LINE(nr||' rows updated'); DBMS_HS_PASSTHROUGH.CLOSE_CURSOR@salesdb(c); END;
問合せでは、非問合せとは異なり、SELECT
文から結果セットが取得されます。結果セットは、カーソルの反復により取得されます。
図3-2に、パススルーSQL問合せのステップを示します。システムでSELECT
文が解析された後、FETCH_ROW
プロシージャで結果セットの各行をフェッチできます。行がフェッチされた後、GET_VALUE
プロシージャを使用してSELECT構文のリスト項目をプログラム変数に取り出します。すべての行がフェッチされた後に、カーソルをクローズできます。
すべての行をフェッチする必要はありません。カーソルのオープン後は、いつでもカーソルをクローズできます。
次の例では、問合せが実行されます。
DECLARE val VARCHAR2(100); c INTEGER; nr INTEGER; BEGIN c := DBMS_HS_PASSTHROUGH.OPEN_CURSOR@salesdb; DBMS_HS_PASSTHROUGH.PARSE@salesdb(c, 'select ENAME from EMP where DEPTNO=10'); LOOP nr := DBMS_HS_PASSTHROUGH.FETCH_ROW@salesdb(c); EXIT WHEN nr = 0; DBMS_HS_PASSTHROUGH.GET_VALUE@salesdb(c, 1, val); DBMS_OUTPUT.PUT_LINE(val); END LOOP; DBMS_HS_PASSTHROUGH.CLOSE_CURSOR@salesdb(c); END;
SELECT
文の解析後は、FETCH_ROW
ファンクションが0
(ゼロ)を戻すまで、ループ内で行がフェッチされて出力されます。
各種リレーショナル・データベースでは、ストアド・プロシージャで結果セットを戻すことができます。つまり、ストアド・プロシージャで1つ以上の行セットを戻すことができます。
従来、データベースのストアド・プロシージャの動作は、高水準プログラミング言語のプロシージャと同じでした。引数の数は一定で、IN
、OUT
またはIN OUT
型を使用できました。プロシージャにn
引数が指定されている場合は、結果として最大n
個の値が戻されます。ただし、ストアド・プロシージャでSELECT * FROM emp
などの問合せを実行して結果を戻す必要がある場合があります。emp
表の列数は固定ですが、プロシージャの作成時には行数を指示する手段がありません。このため、このような問合せの結果を戻す従来のストアド・プロシージャを作成できませんでした。その結果、複数のリレーショナル・データベース・ベンダーがストアド・プロシージャから結果セットを戻す機能を追加していますが、戻す方法はリレーショナル・データベースごとに異なっています。
Oracleには、REF CURSOR
というデータ型が用意されています。ストアド・プロシージャでは、他のすべてのOracleデータ型と同様に、このデータ型をIN
またはOUT
引数として使用できます。Oracleでは、ストアド・プロシージャにはREF CURSOR
型の出力引数が必要です。次に、SQL文のカーソルをオープンし、その出力パラメータのそのカーソルにハンドルを置きます。これにより、コール元は他のカーソルの場合と同じ方法でREF CURSOR
からフェッチできます。
Oracleでは、単に結果セットを戻す以上の操作を実行できます。REF CURSOR
をPL/SQLルーチンに入力引数として渡し、クライアント・プログラムとPL/SQLルーチン間、または複数のPL/SQLルーチン間でやりとりできます。
この項の内容は、次のとおりです。
Oracle以外のシステムでの結果セットのサポート
異機種間サービスでの結果セットのサポート
Oracle以外の複数のシステムで、ストアド・プロシージャにより結果セットを戻すことができますが、その方法はまったく異なります。DB2、Sybase、Microsoft SQL ServerおよびInformixでは、結果セットがある程度までサポートされています。これらのデータベースでの結果セットのサポートは、次の2つのモデルのどちらかに基づいています。
ユーザーは、ストアド・プロシージャの作成時に、そのストアド・プロシージャが戻すことのできる結果セットの最大数を明示的に指定できます。実行時には、ストアド・プロシージャは0(ゼロ)から事前に指定された最大数の範囲内で結果セットをオープンできます。ストアド・プロシージャの実行後に、クライアント・プログラムは埋込みSQLディレクティブを使用するか、クライアントのライブラリ・ファンクションをコールして、これらの結果セットへのハンドルを取得できます。その後、クライアント・プログラムは通常のカーソルの場合と同じ方法で結果セットからフェッチできます。
このモデルでは、ストアド・プロシージャが戻すことのできる結果セット数についての事前指定の制限はありません。モデル1とOracleには制限があります。Oracleの場合、ストアド・プロシージャから戻される結果セットの数はREF CURSOR OUT
引数の数の範囲内です。モデル1の場合は、ストアド・プロシージャ言語によるディレクティブを使用して上限が指定されます。また、Oracleおよびモデル1とは異なり、モデル2では結果セットへのハンドルが戻されるかわりに、ストアド・プロシージャからの戻り時に結果セット全体が戻されます。Oracleの場合のハンドルは、REF CURSOR OUT
引数です。モデル1の場合は、ストアド・プロシージャの実行後に別個に取得されます。Oracleとモデル1のどちらの場合も、ハンドルが取得されると、結果セットからのデータがハンドルでのフェッチにより取得されます。複数のカーソルをオープンして任意の順序でフェッチできます。ただし、モデル2の場合は、すべてのデータがすでにフェッチされており、結果セットはストアド・プロシージャにより決定された順序で戻され、プロシージャの出力引数が最後になります。そのため、すべての結果がフェッチされるまで、最初の結果セット全体がフェッチされてから次の結果セット全体というように順番にフェッチされる必要があります。最後に、ストアド・プロシージャのOUT
引数がフェッチされる必要があります。
前述のように、Oracle以外のデータベース間では、結果セットのサポートが様々な形式で存在します。これらはいずれも、OracleのREF CURSOR
モデルにマップする必要があります。Oracle以外の各種システム間では動作が大幅に異なるため、異機種間サービスでの結果セットのサポートは、接続先となるOracle以外のシステムに応じて2つの方法のいずれかになります。
異機種間サービスでの結果セットのサポートについては、次の注意事項があります。
結果セットのサポートは異機種間サービスの汎用コードに存在しますが、この機能をゲートウェイで動作させるには、ドライバにも実装する必要があります。結果セットのサポートが実装されていないドライバもあるため、ご使用のゲートウェイでサポートされているかどうかは、そのゲートウェイ固有のマニュアルで確認する必要があります。
異機種間サービスでは、ストアド・プロシージャからのREF CURSOR OUT
引数がサポートされます。IN
およびIN OUT
引数はサポートされません。
REF CURSOR OUT
引数は、すべて匿名のREF CURSOR
となります。異機種間サービスでは、型指定のあるREF CURSOR
は戻されません。
Oracle以外のシステムのストアド・プロシージャから戻される各結果セットは、OracleドライバによりREF CURSOR
型のOUT
引数にマップされます。クライアント・プログラムには、REF CURSOR
型の複数のOUT
引数を持つストアド・プロシージャの情報が表示されます。ストアド・プロシージャの実行後に、クライアント・プログラムはOracleストアド・プロシージャにより戻されるREF CURSOR
の場合と同じ方法で、そのREF CURSOR
からフェッチできます。3.4.1.1項で説明したように、異機種間サービスはゲートウェイへの接続時にカーソル・モードになります。
Oracleでは、特定のストアド・プロシージャが戻すことのできる結果セットの最大数が事前に指定されます。戻される結果セットの数は、ストアド・プロシージャのREF CURSOR OUT
引数の数以下です。戻される結果セットの数は、この上限より少なくてもかまいませんが、上限を超えることはできません。
3.4.1.2項で説明したシステムの場合、戻すことのできる結果セットの最大数が事前に指定されていません。モデル1(3.4.1.1項)の場合は、プロシージャが戻すことのできる結果セットの最大数、およびドライバが異機種間サービスに戻すことのできる結果セットの最大数は、REF CURSOR OUT
引数の数により、ストアド・プロシージャに事前に指定されています。ストアド・プロシージャの実行時に、戻される結果セットが最大数より少なければ、その他のREF CURSOR OUT
引数はNULL
に設定されます。
モデル2のデータベース・サーバーにはもう1つの問題があります。つまり、結果セットはデータベースにより戻された順序で取得する必要があります。このため、これらのデータベースへの接続時には、異機種間サービスをカーソル・モードで実行できません。これらのストアド・プロシージャから戻された結果セットにアクセスするには、異機種間サービスを逐次モードで操作する必要があります。
逐次モードでは、ドライバから戻されるプロシージャ記述に次の情報が含まれます。
リモート・ストアド・プロシージャのすべての入力引数
出力引数はなし
REF CURSOR
型のOUT
引数1つ(ストアド・プロシージャから戻される最初の結果セットに対応)
クライアントは、このREF CURSOR
からフェッチし、仮想パッケージ・ファンクションDBMS_HS_RESULT_SET.GET_NEXT_RESULT_SET
をコールして、次の結果セットに対応するREF CURSOR
をフェッチします。このファンクション・コールは、すべての結果セットがフェッチされるまで繰り返されます。最後に戻される結果セットは、実際にはリモート・ストアド・プロシージャのOUT
引数となります。
逐次モードの主な制限事項は、次のとおりです。
リモート・ストアド・プロシージャから戻された結果セットは、戻された順に取得される必要があります。
ストアド・プロシージャの実行時には、以前に実行されたストアド・プロシージャから戻された結果セットがすべて(データが完全にフェッチされたかどうかに関係なく)クローズされます。
関連項目: ゲートウェイを介した結果セットのサポート方法の詳細は、ご使用のゲートウェイ固有のマニュアルを参照してください。 |
ほとんどのデータベース・システムには、なんらかの形式のデータ・ディクショナリがあります。データ・ディクショナリは、システムの各種ユーザーにより作成されたデータベース・オブジェクトに関する情報のコレクションです。リレーショナル・データベースの場合、データ・ディクショナリはデータベース内のデータに関する情報を含む表およびビューのセットです。これには、システムを使用中のユーザーや、そのユーザーが作成したオブジェクト(表、ビュー、トリガーなど)に関する情報が含まれます。ほとんどの場合、すべてのデータ・ディクショナリには(データベース・システムに関係なく)同じ情報が含まれていますが、情報の編成方法はデータベース・システムごとに異なります。
たとえば、Oracleのデータ・ディクショナリ・ビューALL_CATLOG
には、データベース内の表、ビューおよび順序のリストが表示されます。これには3つの列があり、1列目はオブジェクトの所有者名を示すOWNER
、2列目はオブジェクト名を示すTABLE_NAME
、3列目はタイプを示すTABLE_TYPE
です。このフィールドの値は、オブジェクト型に応じてTABLE
、VIEW
、SEQUENCE
などです。ただし、Sybaseの場合、同じ情報がsysusers
およびsysobjects
という2つの表に格納され、その列名はOracleのALL_CATALOG
表の列名とは異なります。また、Oracleでは、表のタイプはTABLE
またはVIEW
などの値を含む文字列です。Sybaseでは1文字です。たとえば、Sybaseでは、U
はユーザー表、S
はシステム表、V
はビューを意味します。
クライアント・プログラムがSybaseにあるALL_CATALOG
表からの情報を必要とする場合は、ALL_CATALOG@
database_link
を参照する問合せをゲートウェイに送信します。この問合せは、異機種間サービスによりsystables
の該当する問合せに変換されてから、Sybaseに送信されます。次に例を示します。
SELECT SU."name" OWNER, SO."name" TABLE_NAME, DECODE(SO."type", 'U ','TABLE', 'S ', 'TABLE', 'V ', 'VIEW') TABLE_TYPE FROM "dbo"."sysusers"@remote_db SU, "dbo"."sysobjects"@remote_db SO WHERE SU."uid" = SO."uid" AND (SO."type" = 'V' OR SO."type" = 'S' OR SO."type" = 'U');
このように、Oracleデータ・ディクショナリ表に対する問合せからOracle以外のシステムのデータ・ディクショナリ表に対する等価の問合せへの変換をリレーするために、異機種間サービスはOracle以外のシステム用のデータ・ディクショナリ変換を必要とします。データ・ディクショナリ変換は、Oracle以外の1つ以上のシステムのデータ・ディクショナリ表に対するビュー定義(実際にはSELECT
文)です。これらのデータ・ディクショナリ表は、Oracleデータ・ディクショナリ表と同じ列名および同じ情報形式を使用して表示されます。データ・ディクショナリ変換は、前述の例のように単純でない場合もあります。必要な情報が多数の表にまたがって散在している場合も多く、その場合、データ・ディクショナリ変換は、これらの表を複雑に結合したものになります。
また、必要な情報がOracle以外のシステムに存在しないため、Oracleデータ・ディクショナリ表に変換がない場合があります。このような場合、ゲートウェイは変換をまったくアップロードしないように決定するか、または疑似実行という代替アプローチに依存できます。ゲートウェイがデータ・ディクショナリ表を疑似実行する必要がある場合は、それを異機種間サービスに認識させます。異機種間サービスは、ローカル・データベースを問い合せてデータ・ディクショナリ表の記述を取得しますが、データをフェッチするように要求されると行が選択されなかったことをレポートします。
Oracleには、次の5つの日時データ型があります。
TIMESTAMP
TIMESTAMP WITH TIME ZONE
TIMESTAMP WITH LOCAL TIME ZONE
INTERVAL YEAR TO MONTH
INTERVAL DAY TO SECOND
異機種間サービスの汎用コードは、SQLおよびストアド・プロシージャにおいてはOracle日時データ型をサポートします。ただし、異機種間サービスでは、データ・ディクショナリ変換やデータ・ディクショナリ変換を伴う問合せでは、これらのデータ型がサポートされません。
異機種間サービスの汎用コードでOracle日時データ型がサポートされていても、特定のゲートウェイに対するサポートは、Oracle以外のシステム用のドライバに日時のサポートが実装されているかどうかによって異なります。Oracle以外のシステムに制限があるため、サポートがドライバに実装されていても、サポートは部分的になる場合があります。この問題については、該当するゲートウェイのマニュアルを参照してください。
ユーザーは、Oracle以外のシステムのタイムスタンプ書式をゲートウェイ初期化ファイル内で設定する必要があります。設定するパラメータは、HS_NLS_TIMESTAMP_FORMAT
およびHS_NLS_TIMESTAMP_TZ_FORMAT
です。また、ユーザーは初期化ファイル内でHS_TIME_ZONE
を設定し、Oracle以外のシステムのローカル・タイム・ゾーンも設定する必要があります。
関連項目: 日時データ型の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
異機種間サービスは、2フェーズ・コミット・メカニズムの実装のインフラストラクチャを提供します。そのサポート範囲はゲートウェイおよびリモート・システムに応じて異なります。詳細は、各ゲートウェイのマニュアルを参照してください。
関連項目: 2フェーズ・コミット・プロトコルの詳細は、『Oracle Database管理者ガイド』を参照してください。 |
以前のバージョンのゲートウェイでは、LONG
データ型のサポートが限定されていました。LONG
は、最大2GBの文字またはRAWデータ(LONG RAW
)の格納に使用できるOracleのデータ型です。これらの旧バージョンでは、LONG
データは単一のピースとして扱われていたため、LONG
データのサイズが4MBに制限されていました。このため、処理できるデータのサイズにメモリーとネットワーク帯域幅という制限が課されていました。現行のゲートウェイの機能は、異機種間で2GBのLONG
データ全体をサポートするように拡張されています。データはエージェントとOracleサーバー間でピース単位で処理されるため、大きいメモリーおよびネットワーク帯域幅という要件から解放されます。
異機種間サービスの初期化パラメータHS_LONG_PIECE_TRANSFER_SIZE
を使用すると、転送されるピースのサイズを設定できます。たとえば、異機種間ソースから2GBのLONG
データをフェッチする場合を考えます。ピース・サイズが小さくなるほどメモリー所要量が減少しますが、すべてのデータをフェッチするためのラウンドトリップは増加します。ピース・サイズが大きいとラウンドトリップは減少しますが、中間ピースを内部に格納するためのメモリー所要量が増加します。そのため、初期化パラメータを使用して最適のパフォーマンス(つまり、ラウンドトリップ回数とメモリー所要量との最適なトレードオフ)が得られるようにシステムをチューニングできます。この初期化パラメータを設定しなければ、システムではデフォルトでピース・サイズが64KBに設定されます。
注意: この機能を、クライアント側のLONG データに対するピース単位操作と混同しないでください。クライアント側でのピース単位のFETCHおよびINSERT操作は、旧バージョンのゲートウェイで動作しており、今後も動作します。クライアント側での唯一の違いは、旧バージョンのゲートウェイでフェッチできるLONG データは最大4MBのみであったのに対して、このバージョンでは2GBのLONG データ全体をフェッチできることです。これは、4MBがデータ型の最大容量のわずか0.2%にすぎないことを考慮すると、かなりの改善点といえます。 |
SQL*Plus DESCRIBE
コマンドを使用してOracle以外のシステムのオブジェクトを記述できます。ただし、いくつかの制限事項があります。たとえば、異機種間リンクを使用した場合には、パッケージ、順序、シノニムまたは型を記述できません。
この項では、分散環境におけるSQLに対する制約について説明します。これらの制約は、Oracle以外のシステムまたはリモートOracleデータベースへのアクセスが行われる分散環境に適用されます。
この項の内容は、次のとおりです。
リモート参照と異機種間参照
重要な制限事項
注意: 異機種間アクセスに関するルールの多くは、リモート参照にも適用されます。詳細は、『Oracle Database管理者ガイド』の分散データベースの項を参照してください。 |
文は、制限付きではありますが、その文で参照されているデータベース・ノードまたはローカル・ノード上で実行できます。参照されるオブジェクトすべてが1つの参照先ノードに解決される場合、Oracleはそのノードで問合せの実行を試みます。/*+ REMOTE_MAPPED */
または/*+ DRIVING_SITE */
ヒントを使用すると、参照先ノードで強制的に実行できます。文が発行された場所とは異なるノードに転送される場合、その文をリモート・マップ文と呼びます。
リモート・マップ文に対しては、完全なデータ型チェックのサポートがあります。チェックの結果により、一貫したデータ型チェックと完全なデータ型の強制が提供されます。
関連項目: 4.5項「Oracleデータベース・サーバーのSQL構文の処理」 |
文のリモート・マップを可能にする方法には、特定のルールまたは制限が適用されます。これらのルールが遵守されていない場合、エラーが発生します。発行される文にこれらのルールすべてとの一貫性があるかぎり、ルールの適用順序は関係ありません。ルールや制限については、3.10.2項を参照してください。
分散環境でのリモート・マッピングにSQLを使用する場合は、異なる制約が存在します。この分散環境には、Oracle Database Gatewayを介してアクセスされるOracle以外のデータベースのみでなく、リモートのOracleデータベースも含めることができます。
次の項では、分散環境でリモート・マッピングにSQLを使用する場合に存在する様々なルールまたは制限について説明します。
注意: 以降の例では、remote_db はOracle以外のリモート・システム、remote_oracle_db はリモートのOracleサーバーを指します。 |
ルールA: データ定義言語文はリモート・マップできません。
Oracleのデータ定義言語では、ターゲット・オブジェクトの構文にはリモート参照の位置がありません。リモート参照を含むデータ定義言語文は常にローカルに実行されます。異機種間サービスの場合、これは、SQLを使用してOracle以外のデータベースにデータベース・オブジェクトを直接作成できないことを意味します。
ただし、パススルーSQLを使用して間接的に作成する方法があります。次にその例を示します。
DECLARE num_rows INTEGER; BEGIN num_rows := DBMS_HS_PASSTHROUGH.EXECUTE_IMMEDIATE@remote_db ( 'create table x1 (c1 char, c2 int)' ); END;
ルールB: リモート・ターゲット表を使用するINSERT、UPDATEおよびDELETE文はリモート・マップする必要があります。
このルールは、リモートのOracleデータベースよりもOracle以外のリモート・データベースの場合に限定的です。これは、Oracle以外のシステムの表に対するデータ操作言語(DML)文の実行中は、リモート・システムで元のOracleデータベースからデータをフェッチできないためです。
たとえば、ローカルのemp
表からローカルの全従業員をOracle以外のリモートのemp
表に挿入するには、次の文を使用します。
この文は、リモート・データベースにリモート・マップされます。リモート・データベースに送信されるリモート・マップ文には、emp
に関する元のデータベースへのリモート参照が含まれます。このようにリモート・データベースが受信するリモート・リンクを、コールバック・リンクと呼びます。
注意: コールバック・リンクは、汎用の異機種間サービスでサポートされていても、すべての異機種間サービス・エージェントに実装されているとはかぎりません。使用中のデータベース・ゲートウェイでコールバック・リンクが動作するかどうかは、データベース・ゲートウェイのマニュアルを参照して判断してください。 |
特定のゲートウェイにコールバック・リンクがサポートされていない場合、前述のINSERT
文では次のエラーが戻されます。
ORA-02025: all tables in the SQL statement must be at the remote database
このエラーを回避するには、PL/SQLブロックを記述します。次に例を示します。
DECLARE CURSOR remote_insert IS SELECT * FROM emp; BEGIN FOR rec IN remote_insert LOOP INSERT INTO emp@remote_db (empno, ename, deptno) VALUES ( rec.empno, rec.ename, rec.deptno ); END loop; END;
もう1つの特殊な事例には、USER
、USERENV
およびSYSDATE
など、セッション固有のSQL関数が関係します。これらの関数は、元のサイトで実行する必要があります。これらの関数を含むリモート・マップ文には、コールバック・リンクが含まれます。コールバックがサポートされていないOracle以外のデータベースの場合は、(デフォルトで)制限エラーになる可能性があります。
たとえば、次の文を考えてみます。
DELETE FROM emp@remote_db WHERE hiredate > sysdate;
この文は次のエラー・メッセージを戻します。
ORA-02070: database REMOTE_DB does not support special functions in this context
このエラーを解決するには、次のように特殊関数をバインド変数で置き換える必要があります。次に例を示します。
DELETE FROM emp@remote_db WHERE hiredate > :1;
ルールC: NESTED TABLE型の列、ユーザー定義型の列、不透明型の列またはREF型の列を含む表などのオブジェクト機能は、リモート・マップできません。
現在、異機種間アクセスの場合、これらの列型はサポートされていません。したがって、この制限が直接発生することはありません。
ルールD: リモート・サイトでサポートされていない演算子および構成メンバーを含むSQL文は、リモート・マップできません。
つまり、INSERT
、UPDATE
、DELETE
の場合、SQL文は実行できません(ルールBを参照)。ただし、サポートされていない演算子または構成メンバーが、コールバック・リンクで実行できる場合、SQL文を実行できる場合があります。
SELECT
の場合は、その他のルールが対象の文をリモート・マップするように要求していないかぎり、このルールの影響を受ける文でも常に実行できます。このルールの影響を受けるSELECT
文は、リモートのSELECT
操作を介して必要なすべてのデータをフェッチし、サポートされない演算子を処理するか、ローカルSQLエンジンを使用してローカルに構成することにより実行されます。
リモートのSELECT
操作とは、ローカル表データの行を取得する操作とは異なり、リモート表データの行を取得する操作です。リモートSELECT
の場合の最悪のケースは、全表スキャンです。全表スキャンは、リモート表のすべてのデータをネットワークを介してフィルタせずにフェッチすることです(SELECT * FROM EMP
など)。
全表スキャンは高コストであるため、Oracleでは回避するよう試みます。リモート表に使用可能な索引がある場合は、ネットワークでフェッチされる行の数を減らすために、これらの索引をWHERE
句の条件で使用します。
Oracleサーバーにより生成されたSQL文をチェックするには、その文を記述し、REMOTE
操作ごとにEXPLAIN PLAN表のOTHER
列を問い合せます。
関連項目: リモート参照を含むEXPLAIN PLANを解析する方法の詳細は、3.11.1項を参照してください。 |
たとえば、次の文を考えてみます。
SELECT COUNT(*) FROM emp@remote_db WHERE hiredate < sysdate;
この文では次の出力が戻されます。
COUNT(*) ---------- 14 1 row selected.
リモート表スキャンは次のとおりです。
SELECT hiredate FROM emp;
sysdate
はremote_db
または評価ルールでサポートされていないため、フィルタに変換される条件を生成してリモート操作に渡すことはできません。そのため、sysdate
はローカルに実行する必要があります。
注意: リモート表スキャン操作は元の問合せについては一部のみ関連するため、受信行数が予想より大幅に多くなり、パフォーマンスが大幅に低下する場合があります。 |
ルールE: 表の式を含むSQL文はリモート・マップできません。
異機種間アクセス・モジュールでは表の式がサポートされていないため、この制限が直接発生することはありません。
ルールF: SQL文でLONGデータが選択される場合は、その文をLONGを含む表が常駐するノードにマップする必要があります。
次のタイプの文を考えてみます。
SELECT long1 FROM table_with_long@remote_db, dual;
(コールバック・リンクがサポートされていない場合)前述の文は次のエラー・メッセージを戻します。
ORA-02025: all tables in the SQL statement must be at the remote database
ルールG: SQL文がSELECT...FOR UPDATE OF...形式の場合、その文はFOR UPDATE OF句で参照される列を持つ表が常駐するノードにマップする必要があります。
SQL文がSELECT...FOR UPDATE OF...
形式の場合、その文はFOR UPDATE OF
句で参照される列を持つ表が常駐するノードにマップする必要があります。
たとえば、次の文を考えてみます。
SELECT ename FROM emp@remote_db WHERE hiredate < sysdate FOR UPDATE OF empno;
前述の文は、リモート・マップが不可能な場合、次のエラー・メッセージを戻します。
ORA-02070: database REMOTE_DB does not support special functions in this context
ルールH: SQL文にSEQUENCEまたは順序が含まれている場合は、その文を各順序が常駐するサイトにマップする必要があります。
リモートではOracle以外の順序はサポートされないため、このルールが異機種間アクセス・モジュールに適用されることはありません。
ルールI: 文に1つ以上のユーザー定義演算子が含まれている場合は、その文を各演算子が定義されているノードにマップする必要があります。
文にユーザー定義演算子が含まれている場合は、その文全体をその演算子が定義されているデータベース・ノードにリモート・マップする必要があります。
ルールJ: 重複するバインド変数を含む文はリモート・マップできません。
この制限を回避するには、一意のバインド変数を使用して数値でバインドします。
Oracleのオプティマイザを異機種間サービスと併用できます。異機種間サービスは、Oracle以外のシステムのそれぞれの表について特定の表および索引統計情報を収集し、この情報をOracleサーバーに渡します。Oracleのコストベース・オプティマイザは、この情報を問合せ計画の作成時に使用します。
その他にも、コストベース・オプティマイザでは複数の最適化が実行されます。最も重要な最適化は、リモート・ソートの排除とリモート結合です。
この項の内容は、次のとおりです。
例: 索引統計と表統計の使用
例: リモート結合の最適化
Oracle以外のアクセスに対するオプティマイザの制限
Oracleデータベースに10行の表を作成する次の文を考えてみます。
CREATE TABLE T1 (C1 number);
DBMS_STATS
パッケージを使用して表を分析します。次に例を示します。
DBMS_STATS.GATHER_TABLE_STATS ('SCOTT','T1'); DBMS_STATS.GENERATE_STATS ('SCOTT','T1');
前述の例では、スキーマ名をSCOTT
とし、表名をT1
としています。DBMS_STATS
パッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
Oracle以外のシステムに1000行を含む表を作成します。
次のSQL文を発行します。
SELECT a.* FROM remote_t1@remote_db a, T1 b WHERE a.C1 = b.C1;
Oracleオプティマイザは、エージェントに対して次のSQL文を発行します。
SELECT C1 FROM remote_t1@remote_db;
この文は、Oracle以外のシステムから1000行すべてをフェッチし、Oracleデータベース内で結合を実行します。
remote_t1
表のC1
列に一意の索引を追加して同じSQL文を再発行すると、エージェントはローカルt1
のC1
の値ごとに次のSQL文を受信します。
... SELECT C1 FROM remote_t1@remote_db WHERE C1 = ?; ...
注意: ? はバインド・パラメータ・マーカーです。また、Oracleにより生成されたバインド変数を含む結合条件は、ネステッド・ループ結合方法についてのみ生成されます。 |
SQL実行計画を確認するには、SQL文のEXPLAIN PLANを生成します。最初に、admin
ディレクトリにutlxplan
をロードします。
次のように入力します。
EXPLAIN PLAN FOR SELECT a.* FROM remote_t1@remote_db a, T1 b WHERE a.C1 = b.C1;
次の文を入力してutlxpls
ユーティリティ・スクリプトを実行します。
@utlxpls
操作REMOTE
は、リモートSQLが参照されていることを示します。
どの文が送信されるかを確認するには、次の文を入力します。
SELECT ID, OTHER FROM PLAN_TABLE WHERE OPERATION = 'REMOTE';
ここでは、Oracleデータベースのリモート結合最適化機能の例を示します。
注意: Oracle以外のシステムからの表を使用するEXPLAIN PLANは、ローカルまたはリモートのOracle表スキャンを使用する同様の文とは異なる場合があります。これは、Oracle以外の表についてOracleで使用可能な統計に制限があるためです。最も重要なのは、Oracle以外の表の非一意索引には列を選択できないことです。使用可能な統計に制限があるため、次の例はリモート結合を実際に実行したときの内容とは異なる場合があり、あくまでも一例にすぎません。 |
次の例を考えてみます。
EXPLAIN PLAN FOR SELECT e.ename, d.dname, f.ename, f.deptno FROM dept d, emp@remote_db e, emp@remote_db f WHERE e.mgr = f.empno AND e.deptno = d.deptno AND e.empno = f.empno; @utlxpls
次のような出力が表示されます。
PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost | Inst |IN-OUT| --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2000 | 197K| 205 | |* 1 | HASH JOIN | | 2000 | 197K| 205 | | 2 | TABLE ACCESS FULL | DEPT | 21 | 462 | 2 | |* 3 | HASH JOIN | | 2000 | 154K| 201 | | 4 | REMOTE | | 2000 | 66000 | 52 | | 5 | REMOTE | | 2000 | 92000 | 52 | --------------------------------------------------------------------------- PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Query Block Name / Hint Alias (identified by operation id): ----------------------------------------------------------- 1 - sel$1 / D 2 - sel$1 / D 3 - sel$1 / F 4 - sel$1 / F 5 - sel$1 / E Predicate Information (identified by operation id): PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- --------------------------------------------------- 1 - access("E"."DEPTNO"="D"."DEPTNO") 3 - access("E"."MGR"="F"."EMPNO" AND "E"."EMPNO"="F"."EMPNO")
次の文を発行します。
SET long 300 SELECT other FROM plan_table WHERE operation = 'REMOTE';
次のような出力が表示されます。
OTHER -------------------------------------------------------------------------------- SELECT "EMPNO","ENAME","DEPTNO" FROM "EMP" SELECT "EMPNO","ENAME","MGR","DEPTNO" FROM "EMP" SELECT "EMPNO","ENAME","DEPTNO" FROM "EMP" SELECT "EMPNO","ENAME","MGR","DEPTNO" FROM "EMP"
次に、Oracle以外のシステムへのアクセスに対するオプティマイザの制限を示します。
リモート・オブジェクトに関する列統計情報はありません。このため、適切な実行計画が得られない場合があります。実行計画を検証し、ヒントを使用して最適化してください。
リモート結合を強制実行するためのオプティマイザ・ヒントはありません。ただし、リモート問合せブロックの最適化機能は用意されています。この機能を使用すると、リモート結合を取得するために問合せを少しリライトできます。
前項の例の記述は、次の形式にリライトできます。
SELECT v.ename, d.dname, d.deptno FROM dept d, (SELECT /*+ NO_MERGE */ e.deptno deptno, e.ename ename emp@remote_db e, emp@remote_db f WHERE e.mgr = f.empno AND e.empno = f.empno; ) WHERE v.deptno = d.deptno;
この例では、リモート結合が保証されています。これは、NO_MERGE
ヒントを使用してネストした問合せ内に分離されるためです。