7 SQLセマンティクスとLOB

LOBに対しては様々なSQLセマンティクスがサポートされています。

この章で説明する技法では、一部の操作にLOB固有のAPIを使用するかわりに、SQLコードでLOBを直接使用できます。

内容は次のとおりです。

7.1 SQLでのLOBの使用について

SQL文字列演算子やSQLファンクションなど、SQL VARCHAR2セマンティクスを使用して、CLOBデータ型とNCLOBデータ型にアクセスできます。(LENGTHファンクションは、CLOBおよびNCLOBデータ型と同様に、BLOBデータ型でも使用できます)。これらの技法にメリットがあるのは、次の場合です。

  • 比較的小さいサイズ(約100KB以下)のLOBに対して操作を実行する場合。

  • データベースをLONG列からLOBデータ型に移行した後も、既存のPL/SQLアプリケーションのSQL文字列関数がすべて引き続き機能する場合。

次の場合には、SQLセマンティクスをお薦めしません。

  • ランダム・アクセスやピース単位のフェッチなど、高度な機能を使用する場合は、LOB APIを使用してください。

  • 比較的大きいサイズ(1MBを超える場合)のLOBに対しSQLセマンティクスを使用して操作を実行すると、パフォーマンスが低下する可能性がある場合。この場合はLOB APIを使用することをお薦めします。

    ノート:

    SQLセマンティクスは、永続LOBおよび一時LOBとともに使用されます。(BFILEは読取り専用データ型のため、SQLセマンティクスはBFILE列には適用されません。)

7.2 LOBでの使用がサポートされるSQLファンクションおよび演算子

引数としてVARCHAR2列を取る多数のSQL演算子およびファンクションは、LOB列も受け入れます。

7.2.1 LOBのSQLファンクションおよび操作について

次のリストに、LOBでの使用がサポートされるSQLファンクションおよび演算子のカテゴリを示します。個々のファンクションおよび演算子の詳細は、表7-1を参照してください。

  • 連結

  • 比較

    (一部の比較関数は、LOBでの使用がサポートされません。)

  • 文字ファンクション

  • 変換

    (一部の変換関数は、LOBでの使用がサポートされません。)

次のカテゴリのファンクションは、LOBでの使用がサポートされません。

  • 集計ファンクション

    事前定義済の集計関数はLOBでの使用がサポートされませんが、ユーザー定義の集計関数を作成してLOBで使用できることに注意してください。

  • Unicodeファンクション

各ファンクションと演算子の詳細は表7-1のとおりです。この表には、オペランドまたは引数としてVARCHAR2型を取る、またはVARCHAR2値を戻すSQL演算子およびファンクションがリストされています。「SQL」列は、CLOBデータ型とNCLOBデータ型でサポートされるファンクションと演算子を示します。(LENGTHファンクションは、BLOBデータ型でもサポートされます。)

Oracle Databaseで提供されるDBMS_LOB PL/SQLパッケージでは、表7-1の「PL/SQL」列に示すように、ほとんどのファンクションでLOBの使用がサポートされます。

ノート:

表7-1の「SQL」列が「いいえ」となっている演算子およびファンクションは、PL/SQLブロックで使用されるSQL問合せには機能しません。ただし、一部の演算子およびファンクションの場合は、PL/SQLコードでの直接使用がサポートされます。

関連項目:

ユーザー定義の集計関数の詳細は、Oracle Databaseデータ・カートリッジ開発者ガイドを参照してください

7.2.2 CLOB型からCHAR型への暗黙的な変換

表7-1の「SQL」列または「PL/SQL」列が「CNV」となっているファンクションは、CLOBからVARCHAR2などの文字データ型に変換することで実行されます。SQL環境ではCLOBの最初の4KBのみが変換されて操作に使用され、PL/SQL環境ではCLOBの最初の32KBのみが変換されて操作に使用されます。

表7-1 LOBでのSQL VARCHAR2ファンクションおよび演算子

カテゴリ 演算子およびファンクション SQLの例/コメント SQL PL/SQL

連結

||CONCAT()

Select clobCol || clobCol2 from tab;

はい

はい

比較

= , !=, >, >=, <, <=, <>, ^=

if clobCol=clobCol2 then...

いいえ

はい

比較

INNOT IN

if clobCol NOT IN (clob1, clob2, clob3) then...

いいえ

はい

比較

SOMEANYALL

if clobCol < SOME (select clobCol2 from...) then...

いいえ

該当なし

比較

BETWEEN

if clobCol BETWEEN clobCol2 and clobCol3 then...

いいえ

はい

比較

LIKE [ESCAPE]

if clobCol LIKE '%pattern%' then...

はい

はい

比較

IS [NOT] NULL

where clobCol IS NOT NULL

はい

はい

文字ファンクション

INITCAPNLS_INITCAP

select INITCAP(clobCol) from...

CNV

CNV

文字ファンクション

LOWERNLS_LOWERUPPERNLS_UPPER

...where LOWER(clobCol1) = LOWER(clobCol2)

はい

はい

文字ファンクション

LPADRPAD

select RPAD(clobCol, 20, ' La') from...

はい

はい

文字ファンクション

TRIMLTRIMRTRIM

...where RTRIM(LTRIM(clobCol,'ab'), 'xy') = 'cd'

はい

はい

文字ファンクション

REPLACE

select REPLACE(clobCol, 'orig','new') from...

はい

はい

文字ファンクション

SOUNDEX

...where SOUNDEX(clobCOl) = SOUNDEX('SMYTHE')

CNV

CNV

文字ファンクション

SUBSTR

...where substr(clobCol, 1,4) = like 'THIS'

はい

はい

文字ファンクション

TRANSLATE

select TRANSLATE(clobCol, '123abc','NC') from...

CNV

CNV

文字ファンクション

ASCII

select ASCII(clobCol) from...

CNV

CNV

文字ファンクション

INSTR

...where instr(clobCol, 'book') = 11

はい

はい

文字ファンクション

LENGTH

...where length(clobCol) != 7;

はい

はい

文字ファンクション

NLSSORT

...where NLSSORT (clobCol,'NLS_SORT = German') > NLSSORT ('S','NLS_SORT = German')

CNV

CNV

文字ファンクション

INSTRBSUBSTRBLENGTHB

この3つのファンクションは、シングルバイト文字セットを使用するCLOBの場合にのみサポートされます。(LENGTHBは、CLOBと同様、BLOBについてもサポートされます。)

はい

はい

文字関数: 正規表現

REGEXP_LIKE

このファンクションは、文字列内でパターンを検索します。このファンクションを問合せのWHERE句で使用すると、指定した正規表現と一致する行が戻されます。

関連項目:

はい

はい

文字関数: 正規表現

REGEXP_REPLACE

このファンクションは文字列内でパターンを検索し、そのパターンの各出現箇所を指定したパターンで置き換えます。

はい

はい

文字関数: 正規表現

REGEXP_INSTR

このファンクションは、指定した正規表現パターンの出現箇所を文字列内で検索します。検索する出現箇所と検索開始位置を指定します。文字列内で一致が検出された位置を示す整数が戻されます。

はい

はい

文字関数: 正規表現

REGEXP_SUBSTR

このファンクションは、指定した正規表現パターンと一致する実際の部分文字列を戻します。

はい

はい

変換

CHARTOROWID

CHARTOROWID(clobCol)

CNV

CNV

変換

COMPOSE

COMPOSE('string')

CHARVARCHAR2CLOBNCHARNVARCHAR2およびNCLOBデータ型の文字列を与えると、Unicode文字列が返されます。ウムラウト・コードポイントで修飾されたoコード・ポイントは、oウムラウト・コード・ポイントとして返されます。

CNV

CNV

変換

DECOMPOSE

DECOMPOSE('str' [CANONICAL | COMPATIBILITY] )

Unicode文字の引数で有効です。入力と同じ文字セットで分解後にUnicode文字列を戻します。o-umlautコード・ポイントは、oのコード・ポイントの後にウムラウトのコード・ポイントを続けて戻されます。

CNV

CNV

変換

HEXTORAW

HEXTORAW(CLOB)

いいえ

CNV

変換

CONVERT

select CONVERT(clobCol,'WE8DEC','WE8HP') from...

はい

CNV

変換

TO_DATE

TO_DATE(clobCol)

CNV

CNV

変換

TO_NUMBER

TO_NUMBER(clobCol)

CNV

CNV

変換

TO_TIMESTAMP

TO_TIMESTAMP(clobCol)

いいえ

CNV

変換

TO_MULTI_BYTE

TO_SINGLE_BYTE

TO_MULTI_BYTE(clobCol)

TO_SINGLE_BYTE(clobCol)

CNV

CNV

変換

TO_CHAR

TO_CHAR(clobCol)

はい

はい

変換

TO_NCHAR

TO_NCHAR(clobCol)

はい

はい

変換

TO_LOB

INSERT INTO... SELECT TO_LOB(longCol)...

TO_LOBは、LONG列を持つ表をSELECT FROMに指定して、LOB列を持つ表を作成またはその表に挿入する場合にのみ使用できることに注意してください。

該当なし

該当なし

変換

TO_CLOB

TO_CLOB(varchar2Col)

はい

はい

変換

TO_NCLOB

TO_NCLOB(varchar2Clob)

はい

はい

集計ファンクション

COUNT

select count(clobCol) from...

いいえ

該当なし

集計ファンクション

MAXMIN

select MAX(clobCol) from...

いいえ

該当なし

集計ファンクション

GROUPING

select grouping(clobCol) from... group by cube (clobCol);

いいえ

該当なし

その他の関数

GREATESTLEAST

select GREATEST (clobCol1, clobCol2) from...

いいえ

CNV

その他の関数

DECODE

select DECODE(clobCol, condition1, value1, defaultValue) from...

CNV

CNV

その他の関数

NVL

select NVL(clobCol,'NULL') from...

はい

はい

その他の関数

DUMP

select DUMP(clobCol) from...

いいえ

該当なし

その他の関数

VSIZE

select VSIZE(clobCol) from...

いいえ

該当なし

Unicode

INSTR2SUBSTR2LENGTH2LIKE2

これらのファンクションは、UCS2コード・ポイント・セマンティクスを使用します。

いいえ

CNV

Unicode

INSTR4SUBSTR4LENGTH4LIKE4

これらのファンクションは、UCS4コード・ポイント・セマンティクスを使用します。

いいえ

CNV

Unicode

INSTRCSUBSTRCLENGTHCLIKEC

これらのファンクションは、完全なキャラクタ・セマンティクスを使用します。

いいえ

CNV

7.2.3 セッション照合設定に従わないCLOBおよびNCLOB

CLOBおよびNCLOBに対して、最初にVARCHAR2またはNVARCHAR2に変換せずに操作する標準の演算子(表7-1の「SQL」列または「PL/SQL」列で「はい」とマークされているもの)は、REGEXPファンクション以外は、言語的に動作しません。文字データのバイナリ比較は、NLS_COMPおよびNLS_SORTパラメータ設定に関係なく実行されます。

次のREGEXPファンクションは、CLOBまたはNCLOBデータが渡され、言語的比較がVARCHAR2およびNVARCHAR2の値の比較と類似している場合に、例外です。

  • REGEXP_LIKE

  • REGEXP_REPLACE

  • REGEXP_INSTR

  • REGEXP_SUBSTR

  • REGEXP_COUNT

ノート:

CLOBとNCLOBはデフォルトのUSING NLS_COMPオプションをサポートします。

関連項目:

NLS_COMPの詳細は、Oracle Databaseリファレンスを参照してください。

7.2.4 Unicodeのサポート

Unicodeをサポートするために特定のファンクションにはバリエーションが提供されています。

Unicodeサポート用に、INSTRSUBSTRLENGTHおよびLIKEファンクションのバリエーションが用意されています。(これらのバリエーションの場合は、表7-1の「カテゴリ」列が「Unicode」となっています。)

7.2.5 コードポイント・セマンティクス

表7-1に示したINSTRSUBSTRLENGTHおよびLIKEファンクションのコードポイント・セマンティクスは、ファンクションに渡される引数のデータ型に応じて異なります。これらのファンクションでは、次のように、引数がVARCHAR2型かCLOB型かに応じて、異なるコードポイント・セマンティクスが使用されます。

  • 引数がCLOBの場合は、すべての文字セットにUCS2コードポイント・セマンティクスが使用されます。

  • 引数がVARCHAR2などのキャラクタ・タイプの場合は、指定の文字セットにデフォルトのコードポイント・セマンティクスが使用されます。

    • AL16UTF16およびUTF8文字セットにはUCS2コードポイント・セマンティクスが使用されます。

    • AL32UTF8など、他のすべての文字セットにはUCS4コードポイント・セマンティクスが使用されます。

  • 文字データをCLOBまたはNCLOBに格納している場合、CLOBNCLOBに対してデータの読取りまたは書込みを行うすべてのAPIの量パラメータとオフセット・パラメータが、UCS2コードポイントで指定されることに注意してください。一部の文字セットには、完全な1文字が、サロゲート・ペアと呼ばれる1つ以上のUCS2コードポイントで構成されるものがあります。この場合、指定した量またはオフセットが、完全な1文字に分かれないようにする必要があります。これは、文字の部分的な読取りや書込みを回避するためです。

  • 10gから、Oracle Databaseではこのような場合に、読取り/書込み境界で半サロゲート・ペアを検出できます。読取りの場合、オフセットと量が適宜調整されて半分の文字が返されないようになり、その場合、戻される量は要求より少なくなります。書込みの場合はエラーが発生し、宛先のCLOBまたはNCLOBに部分的な文字を上書きして既存のデータを破損しないようにします。

7.2.6 LOBのSQLセマンティクスの戻り値

LOBまたはVARCHAR2を取るファンクションまたは演算子の戻り型は、そのファンクションや演算子に渡された引数のデータ型と同じです。

CONCATなど、2つ以上の引数を取るファンクションは、1つ以上の引数がLOBであればLOBデータ型を戻します。たとえば、CONCAT(CLOB, VARCHAR2)CLOBを戻します。

関連項目:

CONCATファンクションと連結演算子(||)の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

LOBインスタンスは、常にLOBロケータを介してアクセスおよび操作されます。これは戻り値の場合も同じで、SQLファンクションと演算子は、戻り値がLOBインスタンスであればLOBロケータを戻します。

SQLファンクションから戻されるLOBインスタンスは、すべて一時LOBインスタンスです。SQLファンクションが問合せのSELECT構文のリストに使用されている場合にも、そのファンクションにより表内のLOBインスタンス(永続LOB)が変更されることはありません。

7.2.7 LOBに対するLENGTHの戻り値

LENGTHファンクションの戻り値は、渡された引数がLOBであるか文字列であるかに応じて異なります。

  • 長さ0(ゼロ)の文字列が入力されると、LENGTHNULLを戻します。

  • 長さ0(ゼロ)のCLOBの場合、またはEMPTY_CLOB()の戻り値のように空のロケータの場合、LENGTHおよびDBMS_LOB.GETLENGTHファンクションは0(ゼロ)を戻します。

7.3 SQLでのLOBデータ型の暗黙的な変換

一部のLOBデータ型では暗黙的な変換がサポートされ、型間の割当てやパラメータの受渡しなどの操作に使用できます。このような変換はSQLレイヤーで処理され、LOB型を使用するすべてのクライアント・インタフェースで実行できます。

7.3.1 SQLでのCLOBデータ型とNCLOBデータ型の間の暗黙的な変換

データベースでは、CLOBデータ型とNCLOBデータ型の間で、型間の割当てや型間でのパラメータの受渡しなどの操作を実行できます。これらの型間での暗黙的な変換は、文字セット・フォーマットなどのプロパティを保つために必要に応じて実行されます。

暗黙的な変換が発生すると、必要に応じて変換元LOBの各文字が変換先LOBの文字セットに変更されることに注意してください。この場合にデータのサイズが大きいと、パフォーマンスが低下する可能性があります。変換先と変換元の文字セットが同一であれば、パフォーマンスは低下しません。

CLOB型とNCLOB型の間で暗黙的な変換が発生した後、変換先LOBが一時LOBとして暗黙的に作成されます。この新しい一時LOBは、変換元LOBに依存しません。SELECT文で定義操作の一部として暗黙的な変換が発生する場合、次の例に示すように、変換先LOBの変更はそのLOBが選択された表内の永続LOBには影響しません。

SQL> -- check lob length before update 
SQL> select dbms_lob.getlength(ad_sourcetext) from Print_media 
  2       where product_id=3106 and ad_id = 13001; 

DBMS_LOB.GETLENGTH(AD_SOURCETEXT) 
--------------------------------- 
         205 

SQL> 
SQL> declare 
  2   clob1 clob; 
  3   amt number:=10; 
  4  BEGIN 
  5    -- select a clob column into a clob, no implicit convesion 
  6    SELECT ad_sourcetext INTO clob1 FROM Print_media 
  7      WHERE product_id=3106 and ad_id=13001 FOR UPDATE; 
  8 
  9    dbms_lob.trim(clob1, amt); -- Trim the selected lob to 10 bytes 
 10  END; 
 11  / 

PL/SQL procedure successfully completed. 

SQL> -- Modification is performed on clob1 which points to the 
SQL> -- clob column in the table 
SQL> select dbms_lob.getlength(ad_sourcetext) from Print_media 
  2       where product_id=3106 and ad_id = 13001; 

DBMS_LOB.GETLENGTH(AD_SOURCETEXT) 
--------------------------------- 
          10 

SQL> 
SQL> rollback; 

Rollback complete. 

SQL> -- check lob length before update 
SQL> select dbms_lob.getlength(ad_sourcetext) from Print_media 
  2       where product_id=3106 and ad_id = 13001; 

DBMS_LOB.GETLENGTH(AD_SOURCETEXT) 
--------------------------------- 
         205 

SQL> 
SQL> declare 
  2   nclob1 nclob; 
  3   amt number:=10; 
  4  BEGIN 
  5 
  6    -- select a clob column into a nclob, implicit conversion occurs 
  7    SELECT ad_sourcetext INTO nclob1 FROM Print_media 
  8      WHERE product_id=3106 and ad_id=13001 FOR UPDATE; 
  9 
 10    dbms_lob.trim(nclob1, amt); -- Trim the selected lob to 10 bytes 
 11  END; 
 12  / 

PL/SQL procedure successfully completed. 

SQL> -- Modification to nclob1 does not affect the clob in the table, 
SQL> -- because nclob1 is a independent temporary LOB 

SQL> select dbms_lob.getlength(ad_sourcetext) from Print_media 
  2       where product_id=3106 and ad_id = 13001; 

DBMS_LOB.GETLENGTH(AD_SOURCETEXT) 
--------------------------------- 
         205 
  

関連項目:

7.4 SQLでサポートされないLOBの使用

表7-2に、LOB列でサポートされないSQL操作を示します。

表7-2 SQLでサポートされないLOBの使用

サポートされないSQL操作 サポートされない使用方法の例

SELECT DISTINCT

SELECT DISTINCT clobCol from...

SELECT

ORDER BY

SELECT... ORDER BY clobCol

SELECT

GROUP BY

SELECT avg(num) FROM...

GROUP BY clobCol

UNIONINTERSECTMINUS

(UNION ALLは、LOBに対して有効であることに注意してください。)

SELECT clobCol1 from tab1 UNION SELECT clobCol2 from tab2;

問合せの結合

SELECT... FROM... WHERE tab1.clobCol = tab2.clobCol

索引列

CREATE INDEX clobIndx ON tab(clobCol)...

7.5 LOBのVARCHAR2およびRAWセマンティクス

VARCHAR2データ型とRAWデータ型で使用されるセマンティクスは、LOBにも適用されます。

7.5.1 LOBに対するVARCHAR2およびRAWセマンティクスについて

VARCHAR2データ型とRAWデータ型で使用される次のセマンティクスは、LOBにも適用されます。

  • CLOBでのCHARバッファの定義

    CLOB列に対してVARCHAR2を、BLOB列に対してRAWを定義できます。また、VARCHAR2列とRAW列に対してCLOB型とBLOB型を定義できます。

  • CHARバッファまたはVARCHAR2へのCLOB列の選択

    CLOB列がVARCHAR2変数に選択されると、CLOB列に格納されたデータが取り出され、CHARバッファに格納されます。バッファがすべてのCLOBデータを格納できるほど大きくない場合、切捨てエラーが発生し、データはバッファに書き込まれません。SELECT操作が正常に完了すると、VARCHAR2変数は正規の文字バッファとして保持されます。

    対照的に、CLOB列がローカルのCLOB変数に選択された場合、CLOBロケータがフェッチされます。

  • RAWへのBLOB列の選択

    BLOB列がRAW変数に選択されると、BLOBデータがRAWバッファにコピーされます。BLOBのサイズがバッファのサイズを超える場合は、切捨てエラーが発生し、データはバッファに書き込まれません。

7.5.2 SQLファンクションから戻されるLOB

SQLファンクションからLOBが戻される場合、結果として戻されるのは一時LOBです。

アプリケーションでは、一時LOBを、SELECT操作によって戻されたデータ用のローカル記憶域として、次のように参照する必要があります。

  • PL/SQLでは、一時LOBの存続期間は、他のローカルPL/SQLプログラム変数と同じです。後続のSQLまたはPL/SQLのVARCHAR2ファンクションまたは問合せに、PL/SQLのローカル変数として渡すことができます。一時LOBは、プログラム・ブロックの最後にスコープから抜け、LOBが解放されます。これらは、PL/SQLのVARCHAR2変数と同じセマンティクスです。ただし、随時DBMS_LOB.FREETEMPORARY()コールを使用して、ローカルの一時LOBが使用したリソースを解放できます。

    ノート:

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

  • OCIでは、SQL問合せから戻された一時LOBは、常にセッションの存続期間中は存続します。ただし、ユーザー定義の存続期間が存在する場合、一時LOBはユーザー定義の存続期間中に存続します。

    警告:

    一時表領域が、プログラムの問合せから戻されるすべての一時LOB結果を格納するために十分大きいことを確認してください。

次に、CLOB列をVARCHAR2に選択し、結果を、宣言したサイズのCHARバッファとして戻す例を示します。

DECLARE
  vc1 VARCHAR2(32000);
  lb1 CLOB;
  lb2 CLOB;
BEGIN
  SELECT clobCol1 INTO vc1 FROM tab WHERE colID=1;
  -- lb1 is a temporary LOB
  SELECT clobCol2 || clobCol3 INTO lb1 FROM tab WHERE colID=2;

  lb2 := vc1|| lb1;
  -- lb2 is a still temporary LOB, so the persistent data in the database 
  -- is not modified. An update is necessary to modify the table data.
  UPDATE tab SET clobCol1 = lb2 WHERE colID = 1;
  
DBMS_LOB.FREETEMPORARY(lb2); -- Free up the space taken by lb2
<... some more queries ...>
END; -- at the end of the block, lb1 is automatically freed 

7.5.3 VARCHAR2とCLOBでのIS NULLとIS NOT NULLの使用方法

LOB列でIS NULL演算子とIS NOT NULL演算子を使用できます。

LOBで使用すると、IS NULLおよびIS NOT NULL演算子によってLOBロケータが行に格納されているかどうかが判別されます。

ノート:

SQL 92標準では、長さ0(ゼロ)の文字列は、NULL文字列とは区別されます。IS NULLの戻り値は、LOBを渡すかVARCHAR2を渡すかに応じて異なります。

  • IS NULL関数に長さ0(ゼロ)の初期化済LOBを渡すと、0(ゼロ、FALSE)が戻されます。これらのセマンティクスは、SQL標準に準拠しています。

  • IS NULL関数に長さ0(ゼロ)のVARCHAR2を渡すと、TRUEが戻されます。

7.5.4 LOBでのWHERE句の使用方法

WHERE句の条件には、LOB値を比較するファンクションを除き、引数としてLOBを取るSQLファンクションを使用できます。

たとえば、WHERE句の条件にLENGTHファンクションを含めることができます。

CREATE TABLE t (n NUMBER, c CLOB);
INSERT INTO t VALUES (1, 'abc');

SELECT * FROM t WHERE c IS NOT NULL;
SELECT * FROM t WHERE LENGTH(c) > 0;
SELECT * FROM t WHERE c LIKE '%a%';
SELECT * FROM t WHERE SUBSTR(c, 1, 2) LIKE '%b%';
SELECT * FROM t WHERE INSTR(c, 'b') = 2;

7.6 リモートLOBおよびBFILE用の組込みファンクション

関連項目:

リモートのLOBBFILEでサポートされる組込みファンクションおよびユーザー定義ファンクションの詳細は、「リモートLOBおよびBFILE用の組込みファンクション」を参照してください