この章の内容は次のとおりです。
PL/SQLでは、前述したとおり、多数のセマンティクスが変更されました。
|
注意: 特に指定のないかぎり、CLOBおよびVARCHAR2に関する次の説明は、BLOBおよびRAWにも該当します。説明では、BLOBおよびRAWについては特に記載しません。 |
この項の内容は次のとおりです。
PL/SQLでは、CLOBからVARCHAR2およびVARCHAR2からCLOBへの暗黙的なデータ型変換が可能です。これらの変換により、アプリケーションで次の操作を実行できます。
VARCHAR2 PL/SQL変数へのCLOB列の選択
CLOB変数へのVARCHAR2列の選択
CLOBとVARCHAR2間の割当ておよびパラメータの受渡し
PL/SQLにおけるVARCHAR2としてのCLOBへのアクセス
次の例は、CLOBがVARCHAR2として処理された場合の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; /
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への移行時に、次の明示的な変換ファンクションにより他のデータ型とCLOB、NCLOBおよびBLOB間のデータ型の変更が行われます。
TO_CLOB(): VARCHAR2、NVARCHAR2またはNCLOBからCLOBへの変換。
TO_NCLOB: VARCHAR2、NVARCHAR2または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()などの他の明示的な変換ファンクションは、サポートされていません(表10-1「LOBでのSQL VARCHAR2ファンクションおよび演算子」を参照)。変換ファンクションの詳細は、第12章「LONGからLOBへの表列の移行」を参照してください。
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セマンティクスと一貫性があります。
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 will raise 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 will not be 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ブロック、ファンクションまたはプロシージャの終了時に自動的に解放されます。CLOB変数に対してDBMS_LOB.FREETEMPORARYをコールし、明示的に一時LOBを解放してシステム・リソースおよび一時表領域を再生する必要があります。
|
注意: SQL文によりLOBが戻される場合、またはLOBがPL/SQLファンクションまたはプロシージャのOUTパラメータである場合は、一時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.
VARCHAR2と同様に、CLOBを他のCLOBやVARCHAR2と比較する場合、一連の規則によって比較が制御されます。規則は通常、「照合順番」といいます。Oracleでは、CHARおよびVARCHAR2は、CHARの空白埋めのため、順序がわずかに異なります。
通常、CLOBは、VARCHAR2と同じ照合順番に従います。つまり、CLOBを比較するとき、CLOBデータの内容をVARCHAR2バッファに取り出し、そのVARCHAR2を比較する場合と結果が一貫しています。この規則は、CLOB間、CLOBとVARCHAR2間およびCLOBとCHAR間の比較を含む、すべての場合に適用されます。
|
注意: CLOBをCHAR文字列と比較する場合、常にCLOBの文字データがCHAR文字列と比較されます。同様に、2つのCLOBを比較する場合、それぞれのLOBロケータではなく、2つのCLOBのデータ内容が比較されます。 |
CLOBを、文字以外のデータまたはBLOBと比較する必要はありません。比較した場合はエラーが発生します。
ネストしたファンクションによって戻される最終値が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;
SQLファンクションに適用される制限はここにも適用されます。
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;
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
PL/SQLからのSQL文の発行以外、PL/SQL内からのリモートLOB操作の実行(DBMS_LOB)はサポートされていません。