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

内容は次のとおりです。

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

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

ノート:

特に指定のないかぎり、PL/SQLセマンティクス、CLOBおよびVARCHAR2に関するほとんどの説明は、BLOBおよびRAWにも該当します。説明では、BLOBおよびRAWについては特に記載しません。

PL/SQLセマンティクスのサポートは、この項で説明します。

8.2 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;
/

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

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()などの他の明示的な変換ファンクションは、サポートされていません(表7-1を参照)。

ノート:

LOBは重複するLONGバインドをサポートしていません。

関連項目:

変換ファンクションの詳細は、「LONGからLOBへの列の移行」を参照してください

8.3.1 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が必要なかったことに注意してください。

ノート:

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

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

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

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.

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

関連項目:

リモートのLOBおよびBFILEをサポートするPL/SQLファンクションについては、「リモートLOBおよびBFILE用のPL/SQLファンクション」を参照してください