この章では、アプリケーションでLOBを使用する場合に十分に理解しておく必要のあるLOBの使用方法とセマンティクスについて説明します。また、LOBを使用するための様々な技法についても説明します。
この章での永続LOBに関するほとんどの説明は、既存の表にあるLOBを扱うことを前提としています。通常、LOB列を含む表の作成作業は、データベース管理者が行います。
|
関連項目:
|
この章の内容は次のとおりです。
LOB列のセルにアクセスするときに使用する手法は、そのセルの状態に応じて異なります。LOB列のセルの状態は、次のいずれかです。
NULL
表セルは作成されていますが、セルに値またはロケータは保持されていません。
空
セルにロケータを含むLOBインスタンスが存在しますが、値はありません。LOBの長さは0(ゼロ)です。
移入済
セルにはロケータと値を含むLOBインスタンスが存在します。
LOBを含む行をロックして、トランザクション中に他のデータベース・ユーザーがLOBに書き込むのを防止できます。LOBを含む行をロックするには、行の選択時にFOR UPDATE句を指定します。行をロックすると、トランザクションを終了するまで他のユーザーはそのLOBをロックまたは更新できません。
LOB APIには、LOBインスタンスを明示的にオープンおよびクローズできる操作が組み込まれています。永続LOBインスタンスは、BLOB、CLOB、NCLOBまたはBFILEなど、どの型の場合にもオープンおよびクローズできます。LOBをオープンすると、次の一方または両方の結果となります。
LOBを読取り専用モードでオープンした場合
この場合、LOB(LOBロケータとLOB値の両方)は、明示的にクローズするまではセッションで変更できません。たとえば、このモードでオープンすることで、重要な操作でLOBを使用しているときに、そのLOBがプログラムの他の部分により変更されないようにできます。操作の実行後に、LOBをクローズできます。
LOBを読取り/書込みモードでオープンした場合(通常のBLOB、CLOBまたはNCLOBインスタンスのみ)
LOBを読取り/書込みモードでオープンすると、そのLOBをクローズするまでLOB列の索引メンテナンスが遅延されます。このモードでのLOBのオープンが役立つのは、LOB列に拡張可能索引があり、そのLOBに書込みを行うたびにデータベースで索引メンテナンスが実行されるのを避ける場合のみです。オープンしているLOBに対して複数の書込み操作を実行する場合は、この方法でオープンするとアプリケーションのパフォーマンスを改善できます。
オープンしたLOBは、セッションのいずれかの時点でクローズする必要があります。これは、オープンしているLOBに対する唯一の要件です。LOBインスタンスがオープンしている間は、オープン時のモードで許可されている操作であれば、LOBに対して必要な数の操作を実行できます。
LOB値にアクセスして変更するには、次の2つの方法があります。
OCIのLOB用データ・インタフェースを使用すると、CアプリケーションでCLOB列とBLOB列に対してバインド操作と定義操作を実行できます。これにより、次のように、LOBロケータを使用せずにLOB列にデータを挿入したり、LOB列からデータを選択できます。
LOB列に関連付けられているバインド変数を使用して、CLOBに文字データを挿入するか、BLOBにRAWデータを挿入します。
定義操作を使用してアプリケーションで出力バッファを定義します。このバッファに、CLOBから選択された文字データまたはBLOBから選択されたRAWデータが保持されます。
データベースに格納されたLOBインスタンスの値には、LOBロケータ、つまりLOB値の位置への参照を介してアクセスできます。データベース表では、CLOB、BLOB、NCLOBおよびBFILE列にロケータのみが格納されます。LOBロケータとLOB値に関する注意事項は、次のとおりです。
LOB値にアクセスしたり操作するには、各種のLOB APIにLOBロケータを渡します。
LOBロケータは、同じ型の任意のLOBインスタンスに割り当てることができます。
一時LOBまたは永続LOBの特性は、ロケータには影響しません。この2つの特性はLOBインスタンスにのみ適用されます。
LOB型のBLOB、CLOBおよびNCLOBのロケータとBFILE型のロケータでは、セマンティクスに次のような違いがあることに注意する必要があります。
LOB型のBLOB、CLOBおよびNCLOBの場合、LOB列にはLOB値のロケータが格納されます。各LOBインスタンスは固有のLOBロケータのみでなく、LOB値の固有のコピーも持ちます。
初期化済のBFILE列の場合、行にはBFILEの値を保持する外部オペレーティング・システム・ファイルのロケータが格納されます。行内の各BFILEインスタンスは固有のロケータを持ちますが、2つの異なる行に同じオペレーティング・システム・ファイルを指すBFILEロケータを含めることも可能です。
LOB値の格納場所に関係なく、ロケータは初期化済LOB列の表の行に格納されます。単にロケータという場合は、LOBロケータとBFILEロケータの両方を指すことに注意してください。また、表からLOBを選択した場合、戻されるLOBは常に一時LOBです。一時LOBのロケータの使用方法の詳細は、「SQLファンクションから戻されるLOB」を参照してください。
Oracle Databaseサンプル・スキーマPMのprint_media表は、このマニュアルの多数の例で使用されており、次のように定義されています。
CREATE TABLE print_media
( product_id NUMBER(6)
, ad_id NUMBER(6)
, ad_composite BLOB
, ad_sourcetext CLOB
, ad_finaltext CLOB
, ad_fltextn NCLOB
, ad_textdocs_ntab textdoc_tab
, ad_photo BLOB
, ad_graphic BFILE
, ad_header adheader_typ
) NESTED TABLE ad_textdocs_ntab STORE AS textdocs_nestedtab;
NULLのLOBインスタンスには、ロケータはありません。LOBインスタンスをLOB APIルーチンに渡す前に、そのインスタンスにロケータを含める必要があります。たとえば、行からNULLのLOBを選択できますが、そのインスタンスをPL/SQL DBMS_LOB.READプロシージャには渡せません。次の項では、永続LOB列を初期化する方法とBFILE列を初期化する方法について説明します。
サポートされているプログラム環境(PL/SQL、OCI、OCCI、Pro*C/C++、Pro*COBOL、Visual Basic、JavaまたはOLEDB)を使用してデータを永続LOBに書き込む前に、LOB列およびLOB属性をNULL以外にする必要があります。つまり、ロケータを含める必要があります。
これは、BLOBに対してはEMPTY_BLOBファンクション、CLOBおよびNCLOBに対してはEMPTY_CLOBファンクションを使用して、INSERT文およびUPDATE文で永続LOBを空に初期化することによって行います。
|
注意: SQLを使用すると、NULL値が含まれているLOB列にもデータを移入できます。 |
EMPTY_BLOB()またはEMPTY_CLOB()ファンクションを実行すること自体では例外は発生しません。ただし、空に設定されたLOBロケータを使用して、PL/SQLのDBMS_LOBまたはOCI関数でLOB値に対してアクセスまたは操作すると、例外が発生します。
空のロケータを使用できるのは、INSERT文のVALUES句やUPDATE文のSET句などです。
|
関連項目:
|
|
注意: 文字列は、インスタンス用のデフォルトのキャラクタ・セットを使用して挿入されます。 |
INSERT文はPMのprint_media表において次の操作を実行します。
ad_sourcetextに文字列my Oracleを移入します。
ad_composite、ad_finaltextおよびad_fltextnを空の値に設定します。
ad_photoをNULLに設定します。
ad_graphicを、論理ディレクトリmy_directory_objectにあるmy_pictureファイルを指すように初期化します。
CREATE OR REPLACE DIRECTORY my_directory_object AS 'oracle/work/tklocal';
INSERT INTO print_media VALUES (1726, 1, EMPTY_BLOB(),
'my Oracle', EMPTY_CLOB(), EMPTY_CLOB(),
NULL, NULL, BFILENAME('my_directory_object', 'my_picture'), NULL);
同様に、print_media内のad_header列のLOB属性は、次に示すようにNULL、空、または文字/生のリテラルに初期化できます。
INSERT INTO print_media (product_id, ad_id, ad_header)
VALUES (1726, 1, adheader_typ('AD FOR ORACLE', sysdate,
'Have Grid', EMPTY_BLOB()));
LOBインスタンスにアクセスするには、次の方法があります。
LOBデータ型を使用する列に対するサポートは、多数のSQLファンクションに組み込まれています。このサポートにより、SQLのセマンティクスを使用してSQLでLOB列にアクセスできます。ほとんどの場合は、VARCHAR2列に使用するのと同じSQLセマンティクスをLOB列に対して使用できます。
OCIやPL/SQLのLONG-to-LOB APIを使用すると、直接LOBを選択してCHARバッファまたはRAWバッファに移動できます。次のPL/SQLの例では、ad_finaltextがVARCHAR2バッファfinal_adに移動するように選択されています。
DECLARE
final_ad VARCHAR(32767);
BEGIN
SELECT ad_finaltext INTO final_ad FROM print_media
WHERE product_id = 2056 and ad_id = 12001 ;
/* PUT_LINE can only output up to 255 characters at a time */
...
DBMS_OUTPUT.PUT_LINE(final_ad);
/* more calls to read final_ad */
...
END;
この項では、LOBのルールと制限の詳細を説明します。
LOB列には次のルールと制限があります。
LOBは主キー列として指定できません。
Oracle DatabaseのリモートLOBに対するサポートは限定されています。リモートLOBは、次の3つの形式でサポートされています。
1. AS SELECT形式での表の作成または挿入。
CREATE TABLE t AS SELECT * FROM table1@remote_site;
INSERT INTO t SELECT * FROM table1@remote_site;
UPDATE t SET lobcol = (SELECT lobcol FROM table1@remote_site);
INSERT INTO table1@remote_site SELECT * FROM local_table;
UPDATE table1@remote_site SET lobcol = (SELECT lobcol FROM local_table);
DELETE FROM table1@remote_site <WHERE clause involving non_lob_columns>
前述の例のように構造化された文の場合、SELECT構文のリストに使用できるのはスタンドアロンのLOB列のみです。
2. スカラーを戻すリモートLOB上のファンクション。LOBパラメータを含み、スカラー・データ型を戻すSQLおよびPL/SQLファンクションがサポートされています。他のSQLファンクションとDBMS_LOB APIの場合、リモートのLOB列に対する使用はサポートされていません。たとえば、次の文はサポートされています。
CREATE TABLE tab AS SELECT DBMS_LOB.GETLENGTH@dbs2(clob_col) len FROM tab@dbs2; CREATE TABLE tab AS SELECT LENGTH(clob_col) len FROM tab@dbs2;
ただし、次の文は、DBMS_LOB.SUBSTRがLOBを戻すため、サポートされていません。
CREATE TABLE tab AS SELECT DBMS_LOB.SUBSTR(clob_col) from tab@dbs2;
3. リモートLOB用のデータ・インタフェース。文字またはバイナリのバッファをリモートのCLOBまたはBLOBに挿入、およびリモートのCLOBまたはBLOBを選択して文字またはバイナリのバッファに挿入できます。次にPL/SQLの場合の例を示します。
SELECT clobcol1, type1.blobattr INTO varchar_buf1, raw_buf2 FROM
table1@remote_site;
INSERT INTO table1@remotesite (clobcol1, type1.blobattr) VALUES varchar_buf1,
raw_buf2;
INSERT INTO table1@remotesite (lobcol) VALUES ('test');
UPDATE table1 SET lobcol = 'xxx';
リモート表のLOBに関してサポートされているのは、これらの構文のみです。他の使用方法はサポートされていません。
クラスタには、キー列としてもキー列以外の列としても、LOBを含めることはできません。
次のデータ構造は、一時インスタンスとしてのみサポートされます。この種のインスタンスはデータベース表に格納できません。
任意のLOB型のVARRAY
LOB属性を持つオブジェクト型など、LOB型を含む任意の型のVARRAY
任意のLOB型のANYDATA
LOB型を含む任意の型のANYDATA
問合せのORDER BY句やGROUP BY句または集計ファンクションには、LOB列を指定できません。
SELECT...DISTINCT文やSELECT...UNIQUE文、または結合文には、LOB列を指定できません。ただし、列のオブジェクト型にその型で定義されたMAPファンクションまたはORDERファンクションが含まれている場合、SELECT...DISTINCT文、またはUNIONやMINUS集合演算子を使用する問合せには、オブジェクト型列のLOB属性を指定できます。
LOBセグメントの最初の(INITIAL)エクステントには、3つ以上のデータベース・ブロックを含める必要があります。
AFTER UPDATE DMLトリガーの作成時には、UPDATE OF句にLOB列を指定できません。
LOB列は索引キーの一部として指定できません。ただし、ドメイン索引の索引タイプ指定には、LOB列を指定できます。また、Oracle Textを使用すると、CLOB列に索引を定義できます。
INSERT...AS SELECT操作では、LOB列とLOB属性に最大4,000バイトのデータをバインドできます。
表にLONG列とLOB列の両方がある場合、同一のSQL文でLONG列とLOB列の両方に4,000バイトを超えるデータをバインドすることはできません。ただし、LONG列またはLOB列のいずれか一方には、4,000バイトを超えるデータをバインドできます。
|
注意: OCI関数またはDBMS_LOBパッケージを使用して、LOB列の値またはオブジェクト型列のLOB属性を変更した場合、AFTER UPDATE DMLトリガーを定義した表では、DMLトリガーが起動されません。 |
|
関連項目:
|
その他の一般的なLOBの制限は、次のとおりです。
SQL*Loaderでは、LOBから読み取られたフィールドは句の引数として使用できません。「データをLOBにロードするためのデータベース・ユーティリティ」を参照してください。
共有サーバー(マルチスレッド・サーバー)・モードでのBFILEのセッション移行はサポートされません。これは、オープンされたBFILEに対する操作を、共有サーバーへのコール終了後も継続できることを意味します。BFILE操作が含まれる共有サーバーのセッションは、1台の共有サーバーに限定され、サーバー間での移行はできません。
CLOB列に対する大/小文字を区別しない検索は、多くの場合成功しません。CLOB列に対して大/小文字を区別しない検索を行うには、たとえば次のようにします。
ALTER SESSION SET NLS_COMP=LINGUISTIC; ALTER SESSION SET NLS_SORT=BINARY_CI; SELECT * FROM ci_test WHERE LOWER(clob_col) LIKE 'aa%';
LOWER関数がないとSELECTは失敗します。Oracle Textでは、大/小文字を区別しない検索に対応しています。また、DBMS_LOB.INSTRを使用する方法もあります。第10章「SQLセマンティクスとLOB」を参照してください。