7.1 LOBを使用した暗黙的な変換

この項では、PL/SQLでのLOB型から別のLOB型、またはLOB型から非LOB型への暗黙的な変換プロセスについて説明します。

次の各項の大部分では、print_media表を使用します。次に、print_media表の構造を示します。

図7-1 print_media表

print_media表

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

この項では、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    -- Trim the selected lob to 10 bytes 
  9    DBMS_LOB.TRIM(clob1, amt); 
 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 
  

関連項目:

すべてのデータ型に対してサポートされる暗黙的な変換の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

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

この項では、CLOBデータ型とVARCHAR2データ型の間の暗黙的な変換のサポートについて説明します。

PL/SQLでは、CLOBからVARCHAR2およびVARCHAR2からCLOBへの暗黙的なデータ型変換がサポートされています。

関連項目:

SQL文でのLOBサポートの詳細は、LOBのSQLセマンティクスを参照してください。

ノート:

この項では、簡略化の例としてVARCHAR2データ型を使用していますが、CHARなどの他の文字型もCLOBによる暗黙的な変換に参加できます。

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

CLOBVARCHAR2に割り当てると、CLOB列に格納されているデータが取り出され、VARCHAR2バッファに格納されます。バッファがすべてのCLOBデータを格納できるほど大きくない場合、切捨てエラーが発生し、データはバッファに書き込まれません。これは、VARCHAR2セマンティクスと一貫性があります。この割当て操作が正常に完了すると、VARCHAR2変数はデータを通常の文字バッファとして保持します。この操作は、次の方法で実行できます。
  • SELECT永続または一時CLOBデータをCHARVARCHAR2などの文字バッファ変数に格納します。単一のSELECT文では、このような定義を複数使用できます。
  • CLOBVARCHAR2またはCHAR変数に割り当てます。
  • INSTR関数やSUBSTR関数など、VARCHAR2引数を受け入れる組込みSQL関数およびPL/SQL関数と演算子にCLOBデータ型を渡します。
  • VARCHAR2データ型を受け入れるユーザー定義のPL/SQL関数にCLOBデータ型を渡します。

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

DECLARE
  myStoryBuf VARCHAR2(32000);
  myLob  CLOB;
BEGIN
  -- Select a LOB into a VARCHAR2 variable
  SELECT ad_sourcetext INTO myStoryBuf FROM print_media WHERE ad_id = 12001;
  DBMS_OUTPUT.PUT_LINE(myStoryBuf); 
  -- Assign a LOB to a VARCHAR2 variable
  SELECT ad_sourcetext INTO myLob FROM print_media WHERE ad_id = 12001;
  myStoryBuf := myLob;
  DBMS_OUTPUT.PUT_LINE(myStoryBuf);
END;
/

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

次のシナリオでは、VARCHAR2CLOBに割り当てられます。
  • VARCHAR2またはCHAR変数に格納されているINSERTまたはUPDATE文字データをCLOB列に格納します。このような複数のバインドは、単一のINSERT文またはUPDATE文で使用できます。
  • VARCHAR2またはCHAR変数をCLOB変数に割り当てます。
  • LOBデータ型を受け入れるユーザー定義のPL/SQL関数にVARCHAR2データ型を渡します。
DECLARE
  myLOB CLOB;
BEGIN
  -- Select a VARCHAR2 into a LOB variable
  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));

  -- Insert a VARCHAR2 into a lob column
  INSERT INTO print_media(product_id, ad_id, AD_SOURCETEXT) VALUES (1000, 1, 'ABCDE');

  -- Assign a VARCHAR2 to a LOB variable
  myLob := 'XYZ';
 END;
/

7.1.3 BLOBとRAWの間の暗黙的な変換

この項では、BLOBデータ型とRAWデータ型の間の暗黙的な変換のサポートについて説明します。

特に明記されていないかぎり、CLOBデータ型とVARCHAR2データ型の間の暗黙的な変換のPL/SQLセマンティクスに関連するほとんどの説明は、BLOBデータ型とRAWデータ型の間の暗黙的な変換プロセスにも適用されます。ただし、説明を簡潔にするために、この章のほとんどの例では、BLOBおよびRAWデータ型について明示的に説明していません。BLOBデータ型を含む次の操作では、暗黙的な変換がサポートされます。
  • RAW変数に格納されているINSERTまたはUPDATEバイナリ・データをBLOB列に格納します。このような複数のバインドは、単一のINSERT文またはUPDATE文で使用できます。
  • SELECT永続または一時BLOBデータを、RAWなどのバイナリ・バッファ変数に格納します。このような複数の定義は、単一のSELECT文で使用できます。
  • BLOBRAW変数に割り当てるか、RAWBLOB変数に割り当てます。
  • RAWデータ型を受け入れるように定義された組込みまたはユーザー定義のPL/SQL関数にBLOBデータ型を渡すか、BLOBデータ型を受け入れるように定義された組込みまたはユーザー定義のPL/SQL関数にRAWデータ型を渡します。

7.1.4 LOBを使用した暗黙的な変換のガイドラインおよび制限事項

この項では、LOBのデータ・インタフェースを使用してLOB列またはLOB属性にアクセスする方法について説明します。

CLOBおよびBLOB列または属性からのデータは、INSERTUPDATESELECTなどの通常のSQL文によって参照できます。

PL/SQLには、ピース単位のINSERTUPDATEまたはフェッチ用のルーチンがありません。したがって、LOB列またはLOB属性からアクセスできるデータ量は、PL/SQLの最大文字バッファ・サイズ(32767バイト)によって制限されます。このため、PL/SQLアプリケーションで永続LOB用のデータ・インタフェースを使用してアクセスできるLOBは、32KB未満に制限されます。

データ・インタフェースを使用して32KB -1バイトを超えるサイズのLOBにアクセスする必要がある場合、ピース単位の挿入およびフェッチにAPIを使用するには、PL/SQLコードからJDBCコールまたはOCIコールを実行する必要があります。

データ・インタフェースを使用してLOB列またはLOB属性にアクセスする場合は、次のガイドラインに従ってください。

  • SELECT操作

    PL/SQLでは、LOB列またはLOB属性を選択して文字バッファまたはバイナリ・バッファに格納できます。LOB列またはLOB属性がバッファ・サイズより大きい場合、データはバッファに格納されず、例外が発生します。LOB列またはLOB属性は、LOBロケータとしても選択できます。

  • INSERT操作

    VALUES句の通常のINSERT文を使用して、LOB列またはLOB属性を含む表にINSERTできます。LOB列のフィールドは、リテラル、文字データ型、バイナリ・データ型またはLOBロケータです。

  • UPDATE操作

    LOB列またはLOB属性は、UPDATE... SET文によって全体を更新できます。SET句では、新しい値にリテラル、文字データ型、バイナリ・データ型またはLOBロケータを使用できます。

  • 4000バイトを超えるバインドには制限があります。

    • 表にLONG列とLOB列の両方がある場合、LONG列またはLOB列のいずれかに4000バイトを超えるデータをバインドできますが、同一の文で両方にバインドすることはできません。

    • INSERT AS SELECT操作では、どのような長さのデータもLOB列にバインドできません。

    • 4000バイトを超えるデータをBLOBまたはCLOBにバインドし、そのデータがSQL演算子で構成される場合、結果のサイズは最大4000バイトに制限されます。たとえば、次の文は4000バイトのみ挿入します。LPADの結果は4000バイトに制限されるためです。
      INSERT INTO print_media (ad_sourcetext) VALUES (lpad('a', 5000, 'a'));
    • サイズが4000バイトを超えるデータの場合、データベースでは16進からRAWまたはRAWから16進への暗黙的な変換は実行されません。バッファのサイズが4000バイトを超える場合、文字データのバッファはバイナリ・データ型の列にバインドできず、バイナリ・データのバッファは文字データ型の列にバインドできません。この種のバインドを試みると、列データが4000バイトで切り捨てられます。

      たとえば、バッファのサイズが4000バイトを超える場合は、VARCHAR2バッファをBLOB列にバインドできません。同様に、バッファのサイズが4000バイトを超える場合は、RAWバッファをCLOB列にバインドできません。

7.1.5 LOBを使用した暗黙的な変換の詳細な例

この項の例では、INSERT操作およびUPDATE操作での複数のVARCHARおよびRAWバインドの使用方法を示します。

例7-1 INSERT操作およびUPDATE操作での文字およびRAWバインドの使用

次の例に、INSERT操作およびUPDATE操作でLOB列に文字およびRAWバインドを使用する方法を示します。

DECLARE
  bigtext VARCHAR2(32767);
  smalltext VARCHAR2(2000);
  bigraw RAW (32767);
BEGIN
  bigtext := LPAD('a', 32767, 'a');
  smalltext := LPAD('a', 2000, 'a');
  bigraw := utl_raw.cast_to_raw (bigtext);

  /* Multiple long binds for LOB columns are allowed for INSERT: */
  INSERT INTO print_media(product_id, ad_id, ad_sourcetext, ad_composite)
    VALUES (2004, 1, bigtext, bigraw);

  /* Single long bind for LOB columns is allowed for INSERT: */
  INSERT INTO print_media (product_id, ad_id, ad_sourcetext)
    VALUES (2005, 2, smalltext);  

  bigtext := LPAD('b', 32767, 'b');
  smalltext := LPAD('b', 20, 'a');
  bigraw := utl_raw.cast_to_raw (bigtext);

  /* Multiple long binds for LOB columns are allowed for UPDATE: */
  UPDATE print_media SET ad_sourcetext = bigtext, ad_composite = bigraw,
    ad_finaltext = smalltext;

  /* Single long bind for LOB columns is allowed for UPDATE: */
  UPDATE print_media SET ad_sourcetext = smalltext, ad_finaltext = bigtext;

  /* The following is NOT allowed because we are trying to insert more than
     4000 bytes of data in a LONG and a LOB column: */
  INSERT INTO print_media(product_id, ad_id, ad_sourcetext, press_release)
    VALUES (2030, 3, bigtext, bigtext);
  
  /* Insert of data into LOB attribute is allowed */
  INSERT INTO print_media(product_id, ad_id, ad_header)
     VALUES (2049, 4, adheader_typ(null, null, null, bigraw));

  /* The following is not allowed because we try to perform INSERT AS
     SELECT data INTO LOB */
  INSERT INTO print_media(product_id, ad_id, ad_sourcetext)
    SELECT 2056, 5, bigtext FROM dual;

END;
/

例7-2 SELECTにおけるLOBの複数の定義

次の例に、SQL問合せから複数の永続CLOBまたは一時CLOBを取り出してVARCHAR2変数に、またはBLOBRAW変数に取得するSELECT操作の実行を示します。

DECLARE
  ad_src_buffer    VARCHAR2(32000);
  ad_comp_buffer   RAW(32000);
BEGIN
  /* This retrieves the LOB columns if they are up to 32000 bytes, 
   * otherwise it raises an exception */
  SELECT ad_sourcetext, ad_composite INTO ad_src_buffer, ad_comp_buffer FROM print_media 
    WHERE product_id=2004 AND ad_id=5;

  /* This retrieves the temporary LOB produced by SUBSTR if it is up to 32000 bytes, 
   * otherwise it raises an exception */  
  SELECT substr(ad_sourcetext, 2) INTO ad_src_buffer FROM print_media 
    WHERE product_id=2004 AND ad_id=5;END;
/

例7-3 BLOBRAWの間の暗黙的な変換

暗黙的な割当ては、次の例に示すように、明示的に宣言された変数と、%TYPE属性を使用して既存の列の型を参照することで宣言された変数に対して機能します。この例では、t表のlong_col列がLONGからCLOB列に移行されたものとします。

CREATE TABLE t (long_col LONG); -- Alter this table to change LONG column to LOB
DECLARE
   a VARCHAR2(100);
   b t.long_col%type; -- This variable changes from LONG to CLOB
BEGIN
   SELECT * INTO b FROM t;
   a := b;  -- This changes from "VARCHAR2 := LONG to VARCHAR2 := CLOB
   b := a;  -- This changes from "LONG := VARCHAR2 to CLOB := VARCHAR2 
END;

例7-4 PL/SQLからのPL/SQLプロシージャおよびCプロシージャのコール

PL/SQLまたはCのプロシージャをPL/SQLからコールできます。VARCHAR2が仮パラメータである実パラメータとしてCLOBを渡せ、CLOBが仮パラメータである実パラメータとしてVARCHAR2を渡せます。BLOBおよびRAWに対しても同様です。これにはどのような場合があるかというと、たとえば、仮パラメータまたは実パラメータがアンカー型の場合、つまり変数がtable_name.column_name%type構文を使用して宣言されている場合です。PL/SQLプロシージャまたはファンクションには、CLOBまたはVARCHAR2を仮パラメータとして指定できます。これは、組込みプロシージャおよびユーザー定義プロシージャと関数の両方に適用されます。

次の例は、プロシージャ・コール中の暗黙的な変換を示しています。

CREATE OR REPLACE PROCEDURE foo(vvv IN VARCHAR2, ccc INOUT CLOB) AS
  ...
 BEGIN
  ...
  END;
  /
 DECLARE
  vvv VARCHAR2[32000] := rpad('varchar', 32000, 'varchar')
  ccc CLOB := rpad('clob', 32000, 'clob')
BEGIN
  foo(vvv, ccc); -- No implicit conversion needed here
  foo(ccc, vvv); -- Implicit conversion for both parameters done here
END;
/

例7-5 PL/SQL組込み関数を使用した暗黙的変換

次の例では、PL/SQL組込み関数でのCLOBの使用方法を示します。

DECLARE
  my_ad CLOB;
  revised_ad CLOB;
  myGist VARCHAR2(100):= 'This is my gist.';
  revisedGist VARCHAR2(100);
BEGIN
  INSERT INTO print_media (product_id, ad_id, ad_sourcetext)
    VALUES (2004, 5, 'Source for advertisement 1');  

  -- select a CLOB column into a CLOB variable
  SELECT ad_sourcetext INTO my_ad FROM print_media 
    WHERE product_id=2004 AND ad_id=5;

  -- perform VARCHAR2 operations on a CLOB variable
  revised_ad := UPPER(SUBSTR(my_ad, 1, 20));
 
  -- revised_ad is a temporary LOB
  -- Concat a VARCHAR2 at the end of a CLOB
  revised_ad := revised_ad || myGist;

  -- The following statement raises an error if my_ad is
  -- longer than 100 bytes
  myGist := my_ad;
END;
/