ヘッダーをスキップ
Oracle® Database SecureFilesおよびラージ・オブジェクト開発者ガイド
11gリリース2 (11.2)
B56263-04
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

17 LOBに対するPL/SQLセマンティクス

この章の内容は次のとおりです。

PL/SQL文およびPL/SQL変数

PL/SQLでは、セマンティクスが変更されました。


注意:

特に指定のないかぎり、CLOBおよびVARCHAR2に関する次の説明は、BLOBおよびRAWにも該当します。説明では、BLOBおよびRAWについては特に記載しません。

この項の内容は次のとおりです。

CLOBとVARCHAR2の間の暗黙的な変換

PL/SQLでは、CLOBからVARCHAR2およびVARCHAR2からCLOBへの暗黙的なデータ型変換が可能です。これらの変換により、アプリケーションで次の操作を実行できます。

  • VARCHAR2 PL/SQL変数へのCLOB列の選択

  • CLOB変数へのVARCHAR2列の選択

  • CLOBVARCHAR2間の割当ておよびパラメータの受渡し

PL/SQLにおけるVARCHAR2としてのCLOBへのアクセス

次の例は、CLOBVARCHAR2として処理された場合のCLOBデータへのアクセス方法を示します。

declare
   myStoryBuf VARCHAR2(4001);
BEGIN
   SELECT ad_sourcetext INTO myStoryBuf FROM print_media WHERE ad_id = 12001;
   -- Display Story by printing myStoryBuf directly
END;
/

PL/SQLにおけるVARCHAR2へのCLOBの割当て

declare
myLOB CLOB;
BEGIN
SELECT 'ABCDE' INTO myLOB FROM print_media WHERE ad_id = 11001;
-- myLOB is a temporary LOB.
-- Use myLOB as a lob locator
  DBMS_OUTPUT.PUT_LINE('Is temp? '||DBMS_LOB.ISTEMPORARY(myLOB));
END;
/

明示的な変換ファンクション

SQLおよびPL/SQLでは、LONGからLOBへの移行時に、次の明示的な変換ファンクションにより他のデータ型とCLOBNCLOBおよびBLOB間のデータ型の変更が行われます。

  • TO_CLOB(): VARCHAR2NVARCHAR2またはNCLOBからCLOBへの変換。

  • TO_NCLOB: VARCHAR2NVARCHAR2またはCLOBからNCLOBへの変換。

  • TO_BLOB(): RAWからBLOBへの変換。

  • TO_CHAR(): CLOBからCHAR型への変換。このファンクションを使用して文字LOBをデータベース・キャラクタ・セットに変換する際、変換するLOB値がターゲットのデータ型よりも大きいと、データベースからエラーが返されます。暗黙的な変換でも、LOBデータが適合しない場合はエラーが発生します。

  • TO_NCHAR()NCLOB型をNCHAR型に変換します。このファンクションを使用して文字LOBを各国語キャラクタ・セットに変換する際、変換するLOB値がターゲットのデータ型よりも大きいと、データベースからエラーが返されます。暗黙的な変換でも、LOBデータが適合しない場合はエラーが発生します。

  • CASTは、いずれのLOBデータ型も直接はサポートしていません。CASTを使用してCLOB値を文字データ型に変換する場合、NCLOB値を各国語キャラクタ・データ型に変換する場合、またはBLOB値をRAWデータ型に変換する場合に、データベースが暗黙的にLOB値を文字データまたはRAWデータに変換し、結果の値を明示的にターゲットのデータ型にキャストします。結果の値がターゲットのデータ型よりも大きい場合、データベースからエラーが返されます。

TO_NUMBER()などの他の明示的な変換ファンクションは、サポートされていません(表16-1「LOBでのSQL VARCHAR2ファンクションおよび演算子」を参照)。変換ファンクションの詳細は、第18章「LONGからLOBへの表列の移行」を参照してください。

PL/SQL組込みファンクションでのVARCHAR2およびCLOB

CLOBおよびVARCHAR2は、2つの個別の型です。ただし、使用方法によってはCLOBをSQLおよびPL/SQL VARCHAR2組込みファンクションに渡し、VARCHAR2と同様に使用できます。または、変数をDBMS_LOB APIに渡して、LOBロケータと同様に動作させることができます。次の、「PL/SQLのCLOB変数」の複合的な例を参照してください。

PL/SQL VARCHAR2ファンクションおよび演算子は、CLOBを引数またはオペランドとして取得できます。

VARCHAR2変数のサイズが、CLOBを戻すファンクションの結果、またはCLOB列に対するSELECTの結果を含むために十分大きくない場合はエラーが発生し、操作は実行されません。これは、VARCHAR2セマンティクスと一貫性があります。

PL/SQLのCLOB変数

1 declare
2   myStory CLOB;
3   revisedStory CLOB;
4   myGist VARCHAR2(100);
5   revisedGist VARCHAR2(100);
6 BEGIN
7  -- select a CLOB column into a CLOB variable
8  SELECT Story INTO myStory FROM print_media WHERE product_id=10;
9  -- perform VARCHAR2 operations on a CLOB variable
10 revisedStory := UPPER(SUBSTR(myStory, 100, 1)); 
11 -- revisedStory is a temporary LOB
12 -- Concat a VARCHAR2 at the end of a CLOB
13 revisedStory := revisedStory || myGist;
14 -- The following statement raises an error because myStory is 
15 -- longer than 100 bytes
16 myGist := myStory;
17 END;

「PL/SQLのCLOB変数」の10行目で一時CLOBが暗黙的に作成され、revisedStory CLOBロケータによって指されていることに注意してください。現行のインタフェースでは、この行を次のように展開できます。

buffer VARCHAR2(32000)
DBMS_LOB.CREATETEMPORARY(revisedStory);
buffer := UPPER(DBMS_LOB.SUBSTR(myStory,100,1));
DBMS_LOB.WRITE(revisedStory,length(buffer),1, buffer);

13行目では、myGistが一時LOBの終わりに追加されます。これは、次の文と同じ影響があります。

DBMS_LOB.WRITEAPPEND(revisedStory, myGist, length(myGist));

場合によっては、PL/SQL文で暗黙的に作成された一時LOBは、以前に定義したLOBロケータの表現を変更できます。次の例について考えてみます。

ロケータとデータのリンケージの変更

1 declare
2 myStory CLOB;
3 amt number:=100;
4 buffer VARCHAR2(100):='some data';
5 BEGIN
6 -- select a CLOB column into a CLOB variable
7 SELECT Story INTO myStory FROM print_media WHERE product_id=10;
8 DBMS_LOB.WRITE(myStory, amt, 1, buf);
9 -- write to the persistent LOB in the table
10
11 myStory:= UPPER(SUBSTR(myStory, 100, 1));
12 -- perform VARCHAR2 operations on a CLOB variable, temporary LOB created.
13 -- Changes are not reflected in the database table from this point on.
14 
15 update print_media set Story = myStory WHERE product_id = 10;
16 -- an update is necessary to synchronize the data in the table.
17 END;

7行目以降、myStoryは、print_media内の永続LOBを表します。

8行目のDBMS_LOB.WRITE()コールは、データを直接表に書き込みます。

UPDATE文は不要です。続いて11行目で一時LOBが作成されてmyStoryに割り当てられます。これは、myStoryはローカルのVARCHAR2変数のように使用されているためです。LOBロケータmyStoryは現在、新しく作成された一時LOBを指しています。

したがって、myStoryへの変更は、これ以降はデータベースに反映されません。変更をデータベース表へ伝播するには、UPDATE文が必要になります。以前は、永続LOBにUPDATEが必要なかったことに注意してください。

SELECTまたは割当ての結果としてプログラム・ブロックで作成された一時LOBは、PL/SQLブロック、ファンクションまたはプロシージャの終了時に自動的に解放されます。また、DBMS_LOB.CREATETEMPORARYで作成された一時LOBを解放してシステム・リソースおよび一時表領域を再生する必要があります。このためには、CLOB変数上のDBMS_LOB.FREETEMPORARYをコールします。


注意:

SQL文によりLOBが戻される場合、またはLOBがPL/SQLファンクションまたはプロシージャのOUTパラメータである場合は、一時LOBであるかどうかテストし、一時LOBである場合には操作完了後に解放する必要があります。

一時LOBの自動的および手動による解放

declare
   Story1 CLOB;
   Story2 CLOB;
   StoryCombined CLOB;
   StoryLower CLOB;
BEGIN
   SELECT Story INTO Story1 FROM print_media WHERE product_ID = 1;
   SELECT Story INTO Story2 FROM print_media WHERE product_ID = 2;
   StoryCombined := Story1 || Story2; -- StoryCombined is a temporary LOB
   -- Free the StoryCombined manually to free up space taken
   DBMS_LOB.FREETEMPORARY(StoryCombined);
   StoryLower := LOWER(Story1) || LOWER(Story2);
END; -- At the end of block, StoryLower is freed.

PL/SQL CLOBの比較規則

VARCHAR2と同様に、CLOBを他のCLOBVARCHAR2と比較する場合、一連の規則によって比較が制御されます。規則は通常、「照合順番」といいます。Oracleでは、CHARおよびVARCHAR2は、CHARの空白埋めのため、順序がわずかに異なります。

VARCHAR2の照合順番に従うCLOB

通常、CLOBは、VARCHAR2と同じ照合順番に従います。つまり、CLOBを比較するとき、CLOBデータの内容をVARCHAR2バッファに取り出し、そのVARCHAR2を比較する場合と結果が一貫しています。このルールはCLOBCLOBCLOBVARCHAR2CLOBCHARの比較などすべての場合に適用されます。


注意:

CLOBCHAR文字列と比較するときは、CLOBcharacterデータが必ず文字列と比較されます。同様に、2つのCLOBを比較する場合は、そのLOBロケータではなく、2つのCLOBのデータ・コンテンツが比較されます。

CLOBを、文字以外のデータまたはBLOBと比較する必要はありません。比較した場合はエラーが発生します。

リモートLOBおよびBFILE用のPL/SQLファンクション

ネストしたファンクションによって戻される最終値がLOBでないかぎり、リモート・サイトで実行され、リモートLOBとBFILEを操作する、組込みおよびユーザー定義型PL/SQLファンクションを使用できます。次に例を示します。

SELECT product_id FROM print_media@dbs2 WHERE foo@dbs2(ad_sourcetext, 'aa') > 0;
-- foo is a user-define function returning a NUMBER

DELETE FROM print_media@dbs2 WHERE DBMS_LOB.GETLENGTH@dbs2(ad_graphic) = 0;

リモートのユーザー定義型ファンクションの制限

  1. SQLファンクションに適用される制限はここにも適用されます。

  2. 1つのdblink内のファンクションは、他のdblink内のLOBデータを操作できません。たとえば、次の文はサポートされていません。

    SELECT a.product_id FROM print_media@dbs1 a, print_media@dbs2 b WHERE 
       CONTAINS@dbs1(b.ad_sourcetext, 'aa') > 0;
    
  3. 1つの問合せブロックに、異なるdblinkの表およびファンクションを含めることはできません。たとえば、次の文はサポートされていません。

    SELECT a.product_id FROM print_media@dbs2 a, print_media@dbs3 b
        WHERE CONTAINS@dbs2(a.ad_sourcetext, 'aa') > 0 AND
        foo@dbs3(b.ad_sourcetext) > 0;
    --  foo is a user-defined function in dbs3
    
  4. PL/SQLからのSQL文の発行以外、PL/SQL内からのリモートLOB操作の実行(DBMS_LOB)はサポートされていません。

PL/SQL、OCIおよびJDBC内のリモート・ファンクション

PL/SQL、OCIおよびJDBC内から実行される場合、前述のSQL文はすべて同様に機能します。追加機能はありません。