この章は、次の項目で構成されています。
OCIには、データベース内のラージ・オブジェクト(Large Object: LOB)で操作を実行するための一連の関数があります。永続LOB(BLOB
、CLOB
、NCLOB
)はデータベースの表領域に格納されており、領域の最適化とアクセスの効率化を実現します。これらのLOBは、データベース・サーバーのトランザクションを完全にサポートしています。BFILEとは、データベース表領域外のサーバーのオペレーティング・システム・ファイルに格納された大型のデータ・オブジェクトのことです。
また、OCIは一時LOBもサポートしています。一時LOBは、LOBデータ上で操作するローカル変数のように使用することができます。
BFILE
は読取り専用です。バイナリのBFILE
のみをサポートしています。
関連項目
|
LOBインスタンスは永続的(データベースに格納)または一時的(アプリケーションの有効範囲内のみに存在)のいずれかである可能性があります。永続LOBと永続オブジェクトの概念を混同しないでください。
永続LOBの作成および変更には、次の2つの方法があります。
データ・インタフェースの使用
文字データをCLOB
列に挿入、またはRAW
データをBLOB列に直接挿入すると、LOBを作成できます。SQLのUPDATE
文を使用するか、文字データをCLOB
列にバインドするか、またはRAW
データをBLOB
列にバインドすると、LOBを変更することもできます。
リモート・サーバーとローカル・サーバーがいずれもOracle Database 10g リリース2以上であれば、リモートLOBの(dblinkを介した)挿入、更新および選択がサポートされます。データ・インタフェースでは、最大2GB -1、つまりsb4
の最大サイズまでのデータ・サイズのみサポートされます。
LOBロケータの使用
内部LOBを新規作成するには、OCIDescriptorAlloc()
を使用して新規のLOBロケータを初期化してから、OCIAttrSet()
をコールして(OCI_ATTR_LOBEMPTY
属性を使用して)空に設定し、次に、そのロケータをINSERT
文でプレースホルダにバインドします。この処理により、LOB列または属性がある表に空のロケータを挿入します。次に、SELECT
...FOR
UPDATE
でこの行を選択してロケータを取得し、OCI LOB関数の1つを使用してロケータに書き込みます。
注意: LOB列または属性を変更(書込み、コピー、切捨てなど)するには、そのLOBが含まれている行をロックする必要があります。そのためには、操作を実行する前に SELECT...FOR UPDATE 文を使用してロケータを選択します。 |
LOB書込みコマンドを正常終了するには、トランザクションをオープンしておく必要があります。データの書込み前にトランザクションをコミットする場合は、(SELECT...FOR UPDATE
文の再発行などにより)行を再ロックする必要があります。これは、コミットによってトランザクションがクローズされるためです。
INSERT
文でBFILENAME()
関数を使用すると、外部サーバー側(オペレーティング・システム)ファイルと表内のBFILE
列または属性を関連付けることができます。UPDATE
文でBFILENAME()
を使用して、BFILE
の列または属性を別のオペレーティング・システム・ファイルに関連付けます。OCILobFileSetName()
を使用して、表内のBFILE
をオペレーティング・システム・ファイルに関連付けることもできます。通常、BFILENAME()
はINSERT
またはUPDATE
内でバインド変数なしで使用され、OCILobFileSetName()
がバインド変数に使用されます。
OCIアプリケーションでは、OCIObjectNew()
を使用してLOB属性を持つ永続オブジェクトまたは一時オブジェクトを作成することができます。
OCIを使用して、LOB属性を持つ新規の永続オブジェクトを作成したり、そのLOB属性への書込みができます。LOBロケータを使用するときは、アプリケーションでは次のステップに従います。
OCIObjectNew()
をコールして、LOB属性を持つ永続オブジェクトを作成します。
オブジェクトを「使用済」とマークします。
表に行を挿入して、オブジェクトをフラッシュします。
オブジェクトをデータベースから取り出し、LOBに有効なロケータを取得して、オブジェクトの最新バージョンを再確保します(またはオブジェクトをリフレッシュします)。
オブジェクトのLOBロケータを使用してOCILobWrite()
をコールし、データを書き込みます。
LOB属性への書込み方法はもう1つあります。データ・インタフェースを使用すると、CLOB
属性に対して文字データ、BLOB属性に対してRAW
データをバインドまたは定義できます。
関連項目:
|
アプリケーションでは、OCIObjectNew()
をコールして、内部LOB(BLOB
、CLOB
、NCLOB
)属性を持つ一時オブジェクトを作成できます。ただし、LOB属性を持つ一時オブジェクトは現在サポートされていないため、読取りや書込みなどの、LOB属性での操作は実行できません。一時内部LOB型を作成するためのOCIObjectNew()
コールは失敗しませんが、アプリケーションでは、この一時LOBでLOB操作を使用することはできません。
ただし、アプリケーションでは、BFILE
属性を持つ一時オブジェクトを作成し、BFILE
属性を使用して、サーバーのファイル・システムに格納されているファイルからデータを読み取ることができます。アプリケーションでは、OCIObjectNew()
をコールして、一時BFILE
を作成できます。
LOBを持つOCIの配列インタフェースは、他のデータ型と同じように使用できます。配列インタフェースを使用するには、次の2つの方法があります。
データ・インタフェースの使用
文字データの配列をCLOB
列に対して、またはRAW
データの配列をBLOB
列に対してバインドまたは定義できます。サーバーへの1回のラウンドトリップで、LOBを持つ複数の列を挿入および選択するインタフェースを、配列バインドを使用して定義できます。
関連項目:
|
LOBロケータの使用
LOBロケータを使用するときは、次のように記述子を割り当てる必要があります。
/* First create an array of OCILobLocator pointers: */ OCILobLocator *lobp[10]; for (i=0; i < 10; i++) { OCIDescriptorAlloc (...,&lobp[i],...); /* Then bind the descriptor as follows */ OCIBindByPos(... &lobp[i], ...); }
OCIのOracle Database 10g リリース1からは、4GBより大きいサイズのLOBをサポートする新機能が導入されました。この新機能は、4GBより小さいLOBの新規アプリケーションでも使用できます。
Oracle Databaseでは、データベースのブロック・サイズとは異なるブロックサイズで表領域を作成できます。また、LOBの最大サイズは、表領域ブロックのサイズによって決まります。CHUNK
はLOBストレージのパラメータで、その値はLOBが格納されている表領域のブロック・サイズによって制御されます。LOB列の作成時に、CHUNK
に値を指定できます。この値が、LOB操作に割り当てられるバイト数です。値は、表領域のブロック・サイズの倍数に指定します。倍数でない場合は、次の倍数値に切り上げられます。(表領域のブロック・サイズがデータベースのブロック・サイズと同じ場合は、CHUNK
もデータベースのブロック・サイズの倍数となります。)デフォルトのCHUNK
サイズは表領域の1ブロックで、最大値は32Kです。
たとえば、データベースのブロック・サイズが32Kで、標準以外のブロック・サイズを持つ8Kの表領域を作成するとします。さらに、LOB列を持つテーブルを作成し、CHUNK
サイズを16K(表領域のブロック・サイズである8Kの倍数)に指定するとします。この場合、この列のLOBの最大サイズは(4GB-1)×16Kです。
このマニュアルでは、4GBは4ギガバイト-1、または4,294,967,295バイトと定義します。LOB(永続または一時)の最大サイズは(4GB-1)×(CHUNK
)です。LOBの最大サイズは、8〜128TBの範囲にできます。
BFILE
の最大サイズは、ご使用のオペレーティング・システムで許容される最大ファイル・サイズとUB8MAXVAL
のどちらか小さい方となります。
以前のLOB関数ではub4
を一部のパラメータのデータ型として使用するため、ub4
データ型では最大4GBまでは保持のみできます。より新しい機能では、8バイト長のパラメータ、oraub8
を使用します。これは、oratypes.h
で定義されるデータ型です。コンパイラとオペレーティング・システムに応じて、データ型oraub8
およびorasb8
は該当する64ビット固有のデータ型にマップされます。厳密なANSIオプションを使用して32ビット・モードでコンパイルする場合、マクロを使用してoraub8
およびorasb8
を定義することはできません。
OCILobGetChunkSize()
では、LOBの読取りおよび書込みに使用する値を、BLOB
に対してはバイト数で、CLOB
に対しては文字数で戻します。可変幅のキャラクタ・セットの場合は、値は同じ大きさのUnicode文字数です。チャンクに格納されるバイト数は、内部記憶域のオーバヘッドにより、実際にはCHUNK
パラメータのサイズより小さくなります。関数OCILobGetStorageLimit()
により、現行インストールにおける内部LOBの最大サイズがバイト単位で戻されます。
注意: Oracle Databaseでは、どのようなプログラム環境においても、4GBを超える BFILE はサポートされません。ご使用のオペレーティング・システムのその他のファイル・サイズ制限もBFILE に適用されます。 |
名前が「2」で終わり、データ型ub4
のかわりにデータ型oraub8
を使用する8つの関数がOracle Database 10g リリース1で導入されました。その他、いくつかの問題点を解決するために、読取りおよび書込みの関数(OCILobRead2()
、OCILobWrite2()
およびOCILobWriteAppend2()
)で変更が行われています。
問題点: Oracle Database 10g リリース1より前では、パラメータamtp
により、LOBがバイト長または文字長のどちらであるかが、ロケータ・タイプおよびキャラクタ・セットに基づいて判断されていました。これは複雑で、ユーザーは要件に応じてバイト長または文字長を柔軟に使用することができませんでした。
解決策: 読取り/書込みコールでは、amtp
パラメータのかわりにbyte_amtp
およびchar_amtp
の両方を取ってください。char_amtp
ではCLOB
とNCLOB
のプリファレンスを取ります。char_amtp
が0(ゼロ)の場合、byte_amtp
は入力としてのみ考慮されます。CLOB
およびNCLOB
の出力時には、byte_amtp
とchar_amtp
の両方が格納されます。BLOB
およびBFILE
の場合、入力時も出力時もchar_amtp
パラメータは無視されます。
問題点: OCILobRead2()
では、ポーリング・モードを示すフラグがありません。ユーザーが「100バイトのバッファの空きがあります。可能なかぎり埋めてください。」ということを示す簡単な方法はありません。以前は、空きを埋める文字数を見積る必要がありました。見積りが多すぎた場合は、意図にかかわらず強制的にポーリング・モードになりました。このため、ユーザー・コードはポーリング・モードで取得される可能性があり、後続のOCIコールはすべてブロックされます。
解決策: このコールでは、piece
を入力パラメータとして取ります。OCI_ONE_PIECE
が渡された場合は、byte_amtp
またはchar_amtp
がバッファ長より大きい場合でも、このコールでバッファを可能なかぎり埋め、コールを明示する必要があります。bufl
の値を使用して、読み取るバイトの最大量を指定します。
問題点: ポーリング・モードでLOB書込みをコールした後は、ポーリングの終了までに実際にフェッチされる文字数またはバイト数をユーザーは認識できません。
解決策: ポーリング・モードでの各コール後に、byte_amtp
およびchar_amtp
の両方を更新してください。
問題点: コールバックを使用した、ストリーム・モードでの読取り時または書込み時には、ユーザーはデータの各ピースに対して同じバッファを使用する必要があります。
解決策: コールバック関数には、新規バッファおよびバッファ長を指定する2つの新規パラメータを含めてください。コールバック関数では、新規バッファ・パラメータをNULL
に設定して以前の動作(すべてのピースに対する最初のコールで渡されるデフォルト・バッファを使用)に準拠させる必要があります。
既存のOCIプログラムを拡張して、(4GBより大きい)大容量のLOBデータを処理できます。表7-1に、互換性の問題点をまとめます(「旧」とは、Oracle Database 10g リリース1より前を指します)。
表7-1 LOB関数の互換性および移行
LOB関数 | 旧クライアント/新規または旧サーバー | 新規クライアント/旧サーバー | 新規クライアント/新規サーバー |
---|---|---|---|
|
NA |
ピース・サイズおよびオフセットが< 4GBまではOK |
OK |
|
NA |
ピース・サイズおよびオフセットが< 4GBまではOK |
OK |
|
NA |
LOBサイズ、ピース・サイズ(量)およびオフセットが< 4GBまではOK |
OK |
|
OK(制限は4GB) |
OK |
OK(制限は4GB) |
|
NA |
ピース・サイズおよびオフセットが< 4GBまではOK |
OK |
|
OK(制限は4GB) |
OK |
OK(制限は4GB) |
|
NA |
OK |
OK |
|
OK(制限は4GB) |
OK |
OK(LOBサイズが > 4GBの場合は |
|
NA |
LOBサイズ、ピース・サイズ(量)およびオフセットが< 4GBまではOK |
OK |
|
OK(制限は4GB) |
OK |
OK(制限は4GB) |
|
NA |
LOBサイズ、ピース・サイズ(量)およびオフセットが< 4GBまではOK |
OK |
|
OK(制限は4GB) 新規サーバーを使用した場合: 任意の量>= 4GBを、任意のオフセット< 4GBから読み取ると、 注意: 1) オフセットから最大で4GB-1を読み取る場合は、エラーとして表記されません。 2) ポーリング・モードとともにストリーム・モードを使用すると、> 4GBのピース・サイズを使用しない場合(この場合、> 4GBのデータ読取りが可能)はエラーが戻されません。 |
OK |
OK 任意の量>= 4GBを、任意のオフセット< 4GBから読み取ると、 注意: 1) オフセットから最大で4GB-1を読み取る場合は、エラーとして表記されません。 2) ポーリング・モードとともにストリーム・モードを使用すると、> 4GBのピース・サイズを使用しない場合はエラーが戻されません。 |
|
NA |
OK |
OK |
|
OK(制限は4GB) |
OK |
OK(制限は4GB) |
|
NA |
LOBサイズ、ピース・サイズ(量)およびオフセットが< 4GBまではOK |
OK |
|
OK(制限は4GB) 新規サーバーを使用した場合: 任意の量 >= 4GBを(任意のオフセット< 4GBから)書き込むと、 注意: 最大4GB-1のデータ量を使用して、最大4GB-1の任意のオフセットから10GBのLOBを更新すると、エラーとして表示されません。 |
OK |
OK 任意の量>= 4GBを(任意のオフセット< 4GBから)書き込むと、*amtpの戻り値がオーバーフローするため、 注意: 最大4GB-1のデータ量を使用して、最大4GB-1の任意のオフセットから10GBのLOBを更新すると、エラーとして表示されません。 |
|
NA |
OK(LOBサイズおよびピース・サイズが< 4GBまで) |
OK |
|
OK(制限は4GB) 新規サーバーを使用した場合: 任意の量>= 4GBのデータを追加すると、 |
OK |
OK(制限は4GB) 任意の量>= 4GBのデータを追加すると、 |
|
NA |
エラー |
OK |
新規サーバーおよび新規クライアントを使用するときは、新機能を使用してください。旧機能と新機能を併用すると、予期せぬ状況となる可能性があります。たとえば、OCILobWrite2()
を使用して書き込まれたデータが4GBより大きいときに、アプリケーションでOCILobRead()
を使用してそれを読み取ると、データの一部のみが取得されます(コールバック関数が使用されていない場合)。サイズが4GBを超えていて、旧機能が使用されると、ほとんどの場合、アプリケーションでエラー・メッセージを受け取ります。ただし、サイズが4GBより小さいLOBに対して旧機能を使用する場合は、問題は発生しません。
データへのオフセットを伴うすべてのLOB操作では、オフセットは1から開始されます。OCILobCopy()
、OCILobErase()
、OCILobLoadFromFile()
、OCILobTrim()
などのLOB操作の場合、amount
パラメータは、クライアント側のキャラクタ・セットにかかわらず、CLOB
とNCLOB
の文字数です。
これらのLOB操作は、サーバー上のLOBデータの量を参照します。クライアント側のキャラクタ・セットが可変幅の場合は、次の一般的な規則がLOBコールのamount
パラメータとoffset
パラメータに適用されます。
amount
−amountパラメータがサーバー側のLOBを参照する場合、amountは文字数です。amountパラメータがクライアント側のバッファを参照する場合、amountはバイト数です。
offset
− クライアント側のキャラクタ・セットが可変幅かどうかにかかわらず、offsetパラメータは常にCLOB
またはNCLOB
の場合は文字数で、BLOB
またはBFILE
の場合はバイト数です。
これらの一般的な規則の例外は、特定のLOBコールの説明で示してあります。
次に、パフォーマンスを向上させるためのヒントをいくつか示します。
CLOB
列の文字データまたはBLOB
列のRAW
データをバインドまたは定義できます。ここでは、複数回のラウンドトリップを必要とする従来のLOBインタフェースとは対照的に、LOBを挿入または選択する際に必要とするラウンドトリップは1回のみです。
関連項目:
|
OCILobGetChunkSize()
は、利用可能なチャンク・サイズをBLOBに対してはバイト数で、CLOB
およびNCLOB
に対しては文字数で戻します。 OCILobGetChunkSize()
コールを使用して、BasicFile LOBに関するLOBの読取りおよび書込み操作のパフォーマンスを向上させることができます。サイズが利用可能なチャンク・サイズの倍数で、チャンクの境界から開始するBasicFile LOBデータを使用して読取りまたは書込みが行われると、パフォーマンスが向上します。OCILobGetChunkSize()
の位置合せを使用してSecureFile LOBを読取りまたは書込みする必要はありません。
OCILobGetChunkSize()
のコールにより、LOBの利用可能なチャンク・サイズが戻されるため、アプリケーションは、同じチャンクに対する複数のLOB書込みコールを発行するかわりに、チャンク全体に対する一連の書込み操作をバッチ処理できます。
注意: OCILobGetChunkSize() は、可変幅の文字を格納するLOBに対してLOBチャンクに相当するUnicode文字の数を戻します。 |
OCIでは、LOBの末尾へのデータの書込みをより効率的にするためのショートカットが提供されています。OCILobWriteAppend2()
により、最初にOCILobGetLength()
をコールしてOCILobWrite()
操作の開始点を決定しなくても、データをLOBの末尾に追加できます。OCILobWriteAppend2()
では、両方のステップが行われます。
Oracle OCIでは、内部LOB値の小さな読取りと書込みのために、次のように、LOBのバッファリングを制御するコールを提供します。
これらの関数により、アプリケーションで内部LOB(BLOB
、CLOB
、NCLOB
)を使用して、クライアント側のバッファで小さな読取りと書込みをバッファできるため、パフォーマンスが向上します。これにより、ネットワーク・ラウンドトリップの回数とLOBのバージョンを削減でき、LOBのパフォーマンスが向上します。
関連項目:
|
OCIでは、LOBを明示的にオープンするための関数(OCILobOpen()
)およびLOBをクローズするための関数(OCILobClose()
)と、LOBがオープンされているかどうかをテストするための関数(OCILobIsOpen()
)が提供されています。これらの関数により、一連のLOB操作の開始および終了をマークできるため、LOBのクローズ時に索引の更新など特定の処理が実行できます。
内部LOBでは、オープンされているかどうかの概念は、ロケータではなくLOBに関連しています。ロケータには、LOBの状態に関する情報は格納されません。オープンされている同じLOBを、複数のロケータが指し示すことが可能です。ただし、BFILE
については、オープンは特定のロケータに関連付けられます。したがって、別のロケータを使用して、同じBFILE
に対して複数のオープンが実行されることがあります。
アプリケーションで、LOB操作をOCILobOpen()
コールとOCILobClose()
コールのセットで囲んでいない場合は、LOBが変更されるたびにLOBが暗黙的にオープンおよびクローズされ、それによってLOBの変更に関連付けられているトリガーが起動します。
LOB操作がオープン・コールとクローズ・コールで囲まれていない場合は、LOBの変更時に、LOBの拡張可能な索引がすべて更新されます。このため、索引は常に有効で、任意のタイミングで使用できます。OCILobOpen()
コールとOCILobClose()
コールで囲まれているLOBが変更された場合、個々のLOBの変更に対してトリガーは起動されません。トリガーはOCILobClose()
コールの後にのみ起動されるため、索引が更新されるのはクローズ・コールの後です。したがって、索引はオープン・コールからクローズ・コールまでの間は無効です。OCILobIsOpen()
は、内部LOBおよびBFILE
とともに使用できます。
トランザクションによってオープンされたすべてのLOBをクローズする前にトランザクションをコミットすると、エラーが戻されます。このエラーが戻されると、LOBはオープンとしてマークされなくなりますが、トランザクションは正常にコミットされます。したがって、トランザクションでLOBデータとLOB以外のデータに対して行われた変更はすべてコミットされます。ただし、ドメイン索引とファンクション索引は更新されません。このエラーが戻された場合は、LOB列のファンクション索引とドメイン索引を再作成してください。
トランザクションがない場合にオープンしているLOBは、セッションの終了前にクローズする必要があります。セッションの終了時にオープンしているLOBがある場合、そのLOBはオープンとしてマークされなくなり、ドメイン索引とファンクション索引は更新されません。このエラーが戻された場合は、LOB列のファンクション索引とドメイン索引を再作成します。
LOBのオープンとクローズに関するメカニズムには、次の制限があります。
アプリケーションでは、トランザクションをコミットする前に、以前にオープンしたLOBをすべてクローズする必要があります。これを行わないと、エラーが発生します。トランザクションがロールバックされた場合は、LOBがクローズされないため、変更とともにオープンしているすべてのLOBが破棄され、関連付けられているトリガーは起動しません。
内部LOBのオープン数に制限はありませんが、FILEのオープン数には制限があります。『Oracle Databaseリファレンス』のSESSION_MAX_OPEN_FILESパラメータを参照してください。すでにオープンしているロケータを別のロケータに割り当てても、新規LOBのオープンとしてはカウントされません。
同じトランザクション内で、別のロケータまたは同じロケータを使用して同じ内部LOBを2度オープンまたはクローズすると、エラーになります。
オープンしていないLOBをクローズするとエラーになります。
注意: オープンしているLOBの値をクローズする必要があるトランザクションの定義は、次のいずれかです。
|
OCIでは、読取りおよび書込み用コールバック関数をサポートします。次の項では、コールバックの使用方法を詳しく説明します。
データの挿入または取出しに使用するユーザー定義の読取りおよび書込み用コールバック関数により、LOBをストリーム転送するためのポーリング・メソッドにかわる方法が提供されます。これらの関数はプログラマが実装し、OCILobRead2()
コール、OCILobWriteAppend2()
コールおよびOCILobWrite2()
コールを通じてOCIに登録します。これらのコールバック関数は、必要に応じてOCIでコールします。
ユーザー定義の読取りコールバック関数は、OCILobRead2()
関数を通じて登録されます。コールバック関数には次のプロトタイプが必要です。
CallbackFunctionName
( void *ctxp, CONST void *bufp, oraub8 len, ub1 piece,
void **changed_bufpp, oraub8 *changed_lenp);
最初のパラメータのctxp
はコールバックのコンテキストで、OCILobRead()
ファンクション・コールでOCIに渡されます。コールバック関数がコールされると、ctxp
で提供した情報が戻されます(OCIがINの途中でこの情報を使用することはありません)。bufp
パラメータは、LOBデータが戻される格納場所へのポインタで、bufl
はこのバッファの長さを表します。これにより、指定したバッファに読み取られたデータの量がわかります。
元のOCILobRead2()
コールで提供したバッファの長さが、サーバーから戻されるデータをすべて格納するのに十分でない場合は、ユーザー定義コールバックがコールされます。この場合、piece
パラメータにより、バッファに戻された情報が最初のピース、次のピースまたは最後のピースのどれであるかが示されます。
パラメータchanged_bufpp
およびchanged_lenp
をコールバック関数内部で使用して、バッファを動的に変更できます。changed_bufpp
では、変更したバッファのアドレスを示す必要があり、changed_lenp
では変更したバッファの長さを示す必要があります。アプリケーションによりバッファが動的に変更されない場合は、changed_bufpp
およびchanged_lenp
をコールバック関数内部で使用する必要はありません。
次のコード・フラグメントは、OCILobRead2()
を使用して読取り用コールバック関数を実装します。次の例では、lobl
を前もって選択された有効なロケータと想定します。svchp
は有効なサービス・ハンドルで、errhp
は有効なエラー・ハンドルです。すべてのLOBデータが読み取られるまで、ユーザー定義関数cbk_read_lob()
が繰り返しコールされます。
... oraub8 offset = 1; oraub8 loblen = 0; oraub8 byte_amt = 0; oraub8 char_amt = 0 ub1 bufp[MAXBUFLEN]; sword retval; byte_amtp = 4294967297; /* 4 gigabytes plus 1 */ if (retval = OCILobRead2(svchp, errhp, lobl, &byte_amt, &char_amt, offset, (void *) bufp, (oraub8) MAXBUFLEN, (void *) 0, OCI_FIRST_PIECE, cbk_read_lob, (ub2) 0, (ub1) SQLCS_IMPLICIT)) { (void) printf("ERROR: OCILobRead2() LOB.\n"); report_error(); } ... sb4 cbk_read_lob(ctxp, bufxp, len, piece, changed_bufpp, changed_lenp) void *ctxp; CONST void *bufxp; oraub8 len; ub1 piece; void **changed_bufpp; oraub8 *changed_lenp; { static ub4 piece_count = 0; piece_count++; switch (piece) { case OCI_LAST_PIECE: /*--- buffer processing code goes here ---*/ (void) printf("callback read the %d th piece\n\n", piece_count); piece_count = 0; break; case OCI_FIRST_PIECE: /*--- buffer processing code goes here ---*/ (void) printf("callback read the %d th piece\n", piece_count); /* --Optional code to set changed_bufpp and changed_lenp if the buffer needs to be changed dynamically --*/ break; case OCI_NEXT_PIECE: /*--- buffer processing code goes here ---*/ (void) printf("callback read the %d th piece\n", piece_count); /* --Optional code to set changed_bufpp and changed_lenp if the buffer needs to be changed dynamically --*/ break; default: (void) printf("callback read error: unkown piece = %d.\n", piece); return OCI_ERROR; } return OCI_CONTINUE; }
読取りコールバックと同様に、ユーザー定義の書込みコールバック関数がOCILobWrite2()
関数を通じて登録されます。コールバック関数には次のプロトタイプが必要です。
CallbackFunctionName ( void *ctxp, void *bufp, oraub8 *lenp, ub1 *piecep, void **changed_bufpp, oraub8 *changed_lenp);
最初のパラメータのctxp
はコールバックのコンテキストで、OCILobWrite2()
ファンクション・コールでOCIに渡されます。OCIでコールバック関数がコールされると、ctxp
で提供した情報が戻されます(OCIがINの途中でこの情報を使用することはありません)。bufp
パラメータは記憶領域へのポインタです。このポインタは、OCILobWrite()
へのコールで指定されます。
コールで指定するデータをOCILobWrite2()
に挿入した後も、残りのデータがユーザー定義コールバックによって挿入されます。コールバックでは、bufp
によって示される、記憶域に挿入するデータを指定し、またその長さをbuflp
に指定します。さらに、piecep
パラメータを使用して、次のピース(OCI_NEXT_PIECE
)か最後のピース(OCI_LAST_PIECE
)か示します。アプリケーションで提供する記憶域ポインタに対する全責任はプログラマにあるため、割り当てられた格納領域のサイズ以上は書き込まないようにしてください。
パラメータchanged_bufpp
およびchanged_lenp
をコールバック関数内部で使用して、バッファを動的に変更できます。changed_bufpp
では、変更したバッファのアドレスを示す必要があり、changed_lenp
では変更したバッファの長さを示す必要があります。アプリケーションによりバッファが動的に変更されない場合は、changed_bufpp
およびchanged_lenp
をコールバック関数内部で使用する必要はありません。
次のコード・フラグメントは、OCILobWrite2()
を使用して書込み用コールバック関数を実装します。lobl
を更新用にロックされた有効なロケータと想定します。svchp
は有効なサービス・ハンドルで、errhp
は有効なエラー・ハンドルです。piecep
パラメータにより、アプリケーションが最後のピースを提供していることが示されるまで、ユーザー定義関数cbk_write_lob()
は繰り返しコールされます。
... ub1 bufp[MAXBUFLEN]; oraub8 byte_amt = MAXBUFLEN * 20; oraub8 char_amt = 0; oraub8 offset = 1; oraub8 nbytes = MAXBUFLEN; /*-- code to fill bufp with data goes here. nbytes should reflect the size and should be less than or equal to MAXBUFLEN --*/ if (retval = OCILobWrite2(svchp, errhp, lobl, &byte_amt, &char_amt, offset, (void*)bufp, (ub4)nbytes, OCI_FIRST_PIECE, (void *)0, cbk_write_lob, (ub2) 0, (ub1) SQLCS_IMPLICIT)) { (void) printf("ERROR: OCILobWrite2().\n"); report_error(); return; } ... sb4 cbk_write_lob(ctxp, bufxp, lenp, piecep, changed_bufpp, changed_lenp) void *ctxp; void *bufxp; oraub8 *lenp; ub1 *piecep; void **changed_bufpp; oraub8 *changed_lenp; { /*-- code to fill bufxp with data goes here. *lenp should reflect the size and should be less than or equal to MAXBUFLEN -- */ /* --Optional code to set changed_bufpp and changed_lenp if the buffer needs to be changed dynamically --*/ if (this is the last data buffer) *piecep = OCI_LAST_PIECE; else *piecep = OCI_NEXT_PIECE; return OCI_CONTINUE; }
OCIでは、一時LOBの作成および開放のための関数OCILobCreateTemporary()
およびOCILobFreeTemporary()
と、LOBが一時LOBであるかどうかを判断する関数OCILobIsTemporary()
が提供されています。
一時LOBは、データベース内に永続的に格納されることはありませんが、LOBデータを操作するために、ローカル変数のように動作します。標準(永続)LOB上で動作するOCI関数は、一時LOB上でも使用することができます。
永続LOBと同様に、すべての関数は一時LOBのロケータ上で動作し、実際のLOBデータにはロケータを介してアクセスされます。
一時LOBロケータは、次の型のSQL文への引数として使用できます。
UPDATE
: 一時LOBロケータは、NULLかどうかのテスト時にWHERE
句内の値として使用するか、あるいは関数へのパラメータとして使用できます。一時LOBロケータは、SET
句内で使用することもできます。
DELETE
: 一時LOBロケータは、NULLかどうかのテスト時にWHERE
句内で使用するか、あるいは関数へのパラメータとして使用できます。
SELECT
: 一時LOBロケータは、NULLかどうかのテスト時にWHERE
句内で使用するか、あるいは関数へのパラメータとして使用できます。また、一時LOBは、関数の戻り値を選択する場合、SELECT...INTO
文で戻される変数として使用することもできます。
注意: 永続ロケータを一時ロケータに選択した場合、一時ロケータは永続ロケータによって上書きされます。この場合、一時LOBは暗黙的には解放されません。ユーザーは SELECT...INTO の前に一時LOBを明示的に解放する必要があります。明示的に解放しなければ、一時LOBは継続時間の終了時まで解放されません。同じLOBを指し示している別の一時ロケータがある場合を除き、元のロケータはSELECT...INTO によって上書きされるため、その一時LOBを指し示すロケータは存在しないことになります。 |
OCILobCreateTemporary()
関数を使用して一時LOBを作成します。この関数に渡されるパラメータには、LOBの継続時間を示す値が含まれています。デフォルトの継続時間は、カレント・セッションの長さです。継続時間の終了時に、すべての一時LOBが削除されます。ユーザーは、OCILobFreeTemporary()
関数で一時LOBを明示的に解放することによって、一時LOBの領域を再生できます。一時LOBは、作成されたときは空の状態です。
一時LOBを作成するとき、その一時LOBがサーバーのバッファ・キャッシュに読み取られるかどうかも指定できます。
一時LOBを永続的にするには、OCILobCopy()
を使用して、データを一時LOBから永続LOBにコピーします。また、一時LOBをINSERT
文のVALUES
句で使用したり、UPDATE
文内の割当てのソースとして使用したり、あるいは一時LOBを通常の永続LOB属性に割り当てて、オブジェクトをフラッシュできます。一時LOBは、標準LOBの変更に使用する関数と同じ関数を使用して変更できます。
OCIでは、いくつかの一時LOB用の事前定義済継続時間、およびアプリケーションでアプリケーション固有の継続時間を定義するために使用できる関数のセットが用意されています。事前定義済の継続時間とその関連属性は、次のとおりです。
コール(OCI_DURATION_CALL
)、サーバー側のみ
セッション(OCI_DURATION_SESSION
)
セッション継続時間は、セッションまたは接続が終了した時点で期限切れになります。コール継続時間は、現行のOCIコールが終了した時点で期限切れになります。
オブジェクト・モードで実行している場合は、アプリケーション固有の継続時間も定義できます。アプリケーション固有の継続時間はユーザー期間とも呼ばれ、OCIDurationBegin()
を使用して継続開始時間を指定し、OCIDurationEnd()
を使用して継続終了時間を指定することによって定義されます。
注意: ユーザー定義の継続時間は、アプリケーションがオブジェクト・モードで初期化されている場合にのみ利用できます。 |
アプリケーション固有の継続時間にはそれぞれ、OCIDurationBegin()
で戻される継続時間識別子があり、OCIDurationEnd()
がコールされるまで一意であることが保証されます。アプリケーション固有の継続時間は、セッションの継続時間と同じに設定できます。
継続時間の終了時には、その継続時間に関連付けられたすべての一時LOBが解放されます。一時LOBに関連付けられた記述子は、OCIDescriptorFree()
コールを使用して明示的に解放する必要があります。
ユーザー定義の継続時間ではネストが可能です。つまり、ある継続時間を別のユーザー期間の子の継続時間として定義できます。親の継続時間は子の継続時間を持つことができます。子の継続時間は各自の子の継続時間を持っています。
注意: 継続時間が OCIDurationBegin() で開始されると、パラメータの1つは親の継続時間の識別子となります。親の継続時間が終了すると、子の継続時間もすべて終了します。 |
OCIプログラムがSQLまたはPL/SQLからLOBロケータを取得するたびに、一時ロケータかどうかをチェックします。一時ロケータの場合は、アプリケーションがそこで終了するときに、ロケータを解放します。ロケータは、SELECTまたはOUT BIND中にDEFINEから取得できます。一時LOBの継続時間は、クライアント側に受け渡されるときにセッションに対してアップグレードされます。アプリケーションでは、ロケータが次行のロケータで上書きされる前に次の関数を実行する必要があります。
OCILobIsTemporary(env, err, locator, is_temporary); if(is_temporary) OCILobFreeTemporary(svc, err, locator);
OCILobLocator
ポインタを割り当てるときは、特に注意が必要です。ポインタ割当てにより、LOBの簡単なコピーが作成されます。ポインタの割当て後は、ソースLOBおよびターゲットLOBはデータの同じコピーを指します。これは、割当てを実行するOCILobAssign()
またはOCILobLocatorAssign()
などのLOB APIを使用するのとは異なります。
APIを使用すると、ロケータは割当て後にデータの個別のコピーを論理的に指します。
一時LOBの場合、ポインタ割当て前に、ターゲットとなるLOBロケータの一時LOBが、OCIFreeTemporary()
によって解放されることはプログラマの責任で行ってください。OCILobLocatorAssign()
を使用すると、割当てが発生する前にターゲットLOBロケータ変数の元の一時LOB(ある場合)が解放されます。
SQL文の実行において、アウト・バインド変数を再利用する前に、OCIFreeTemporary()
コールを使用して、既存のアウト・バインドLOBロケータ・バッファ内の一時LOBを解放することはプログラマの責任で行ってください。
次のコードは、一時LOBの使用例を示しています。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <oci.h>
/* Function Prototype */
static void checkerr (/*_ OCIError *errhp, sword status _*/);
sb4 select_and_createtemp (OCILobLocator *lob_loc,
OCIError *errhp,
OCISvcCtx *svchp,
OCIStmt *stmthp,
OCIEnv *envhp);
/* This function reads in a single video Frame from the print_media table.
Then it creates a temporary lob. The temporary LOB which is created is read
through the CACHE, and is automatically cleaned up at the end of the user's
session, if it is not explicitly freed sooner. This function returns OCI_SUCCESS
if it completes successfully or OCI_ERROR if it fails. */
sb4 select_and_createtemp (OCILobLocator *lob_loc,
OCIError *errhp,
OCISvcCtx *svchp,
OCIStmt *stmthp,
OCIEnv *envhp)
{
OCIDefine *defnp1;
OCIBind *bndhp;
text *sqlstmt;
int rowind =1;
ub4 loblen = 0;
OCILobLocator *tblob;
printf ("in select_and_createtemp \n");
if(OCIDescriptorAlloc((void*)envhp, (void **)&tblob,
(ub4)OCI_DTYPE_LOB, (size_t)0, (void**)0))
{
printf("failed in OCIDescriptor Alloc in select_and_createtemp \n");
return OCI_ERROR;
}
/* arbitrarily select where Clip_ID =1 */
sqlstmt=(text *)"SELECT Frame FROM print_media WHERE product_ID = 1 FOR UPDATE";
if (OCIStmtPrepare(stmthp, errhp, sqlstmt, (ub4) strlen((char *)sqlstmt),
(ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT))
{
(void) printf("FAILED: OCIStmtPrepare() sqlstmt\n");
return OCI_ERROR;
}
/* Define for BLOB */
if (OCIDefineByPos(stmthp, &defnp1, errhp, (ub4)1, (void *) &lob_loc, (sb4)0,
(ub2) SQLT_BLOB, (void *)0, (ub2 *)0, (ub2 *)0, (ub4) OCI_DEFAULT))
{
(void) printf("FAILED: Select locator: OCIDefineByPos()\n");
return OCI_ERROR;
}
/* Execute the select and fetch one row */
if (OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,
(CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT))
{
(void) printf("FAILED: OCIStmtExecute() sqlstmt\n");
return OCI_ERROR;
}
if(OCILobCreateTemporary(svchp, errhp, tblob, (ub2)0, SQLCS_IMPLICIT,
OCI_TEMP_BLOB, OCI_ATTR_NOCACHE, OCI_DURATION_SESSION))
{
(void) printf("FAILED: CreateTemporary() \n");
return OCI_ERROR;
}
if (OCILobGetLength(svchp, errhp, lob_loc, &loblen) != OCI_SUCCESS)
{
printf("OCILobGetLength FAILED\n");
return OCI_ERROR;
}
if (OCILobCopy(svchp, errhp, tblob,lob_loc,(ub4)loblen, (ub4) 1, (ub4) 1))
{
printf( "OCILobCopy FAILED \n");
}
if(OCILobFreeTemporary(svchp,errhp,tblob))
{
printf ("FAILED: OCILobFreeTemporary call \n");
return OCI_ERROR;
}
return OCI_SUCCESS;
}
int main(char *argv, int argc)
{
/* OCI Handles */
OCIEnv *envhp;
OCIServer *srvhp;
OCISvcCtx *svchp;
OCIError *errhp;
OCISession *authp;
OCIStmt *stmthp;
OCILobLocator *clob, *blob;
OCILobLocator *lob_loc;
int type =1;
/* Initialize and Logon */
OCIEnvCreate(&envhp, OCI_DEFAULT, (void *)0, 0, 0, 0,
(size_t)0, (void *)0);
(void) OCIHandleAlloc( (void *) envhp, (void **) &errhp, OCI_HTYPE_ERROR,
(size_t) 0, (void **) 0);
/* server contexts */
(void) OCIHandleAlloc( (void *) envhp, (void **) &srvhp, OCI_HTYPE_SERVER,
(size_t) 0, (void **) 0);
/* service context */
(void) OCIHandleAlloc( (void *) envhp, (void **) &svchp, OCI_HTYPE_SVCCTX,
(size_t) 0, (void **) 0);
/* attach to Oracle */
(void) OCIServerAttach( srvhp, errhp, (text *)"", strlen(""), 0);
/* set attribute server context in the service context */
(void) OCIAttrSet ((void *) svchp, OCI_HTYPE_SVCCTX,
(void *)srvhp, (ub4) 0,
OCI_ATTR_SERVER, (OCIError *) errhp);
(void) OCIHandleAlloc((void *) envhp,
(void **)&authp, (ub4) OCI_HTYPE_SESSION,
(size_t) 0, (void **) 0);
(void) OCIAttrSet((void *) authp, (ub4) OCI_HTYPE_SESSION,
(void *) "scott", (ub4)5,
(ub4) OCI_ATTR_USERNAME, errhp);
(void) OCIAttrSet((void *) authp, (ub4) OCI_HTYPE_SESSION,
(void *) "password", (ub4) 5,
(ub4) OCI_ATTR_PASSWORD, errhp);
/* Begin a User Session */
checkerr(errhp, OCISessionBegin ( svchp, errhp, authp, OCI_CRED_RDBMS,
(ub4) OCI_DEFAULT));
(void) OCIAttrSet((void *) svchp, (ub4) OCI_HTYPE_SVCCTX,
(void *) authp, (ub4) 0,
(ub4) OCI_ATTR_SESSION, errhp);
/* ------- Done loggin in ----------------------------------*/
/* allocate a statement handle */
checkerr(errhp, OCIHandleAlloc( (void *) envhp, (void **) &stmthp,
OCI_HTYPE_STMT, (size_t) 0, (void **) 0));
checkerr(errhp, OCIDescriptorAlloc((void *)envhp, (void **)&lob_loc,
(ub4) OCI_DTYPE_LOB, (size_t) 0, (void **) 0));
/* Subroutine calls begin here */
printf("calling select_and_createtemp\n");
select_and_createtemp (lob_loc, errhp, svchp,stmthp,envhp);
return 0;
}
void checkerr(errhp, status)
OCIError *errhp;
sword status;
{
text errbuf[512];
sb4 errcode = 0;
switch (status)
{
case OCI_SUCCESS:
break;
case OCI_SUCCESS_WITH_INFO:
(void) printf("Error - OCI_SUCCESS_WITH_INFO\n");
break;
case OCI_NEED_DATA:
(void) printf("Error - OCI_NEED_DATA\n");
break;
case OCI_NO_DATA:
(void) printf("Error - OCI_NODATA\n");
break;
case OCI_ERROR:
(void) OCIErrorGet((void *)errhp, (ub4) 1, (text *) NULL, &errcode,
errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
(void) printf("Error - %.*s\n", 512, errbuf);
break;
case OCI_INVALID_HANDLE:
(void) printf("Error - OCI_INVALID_HANDLE\n");
break;
case OCI_STILL_EXECUTING:
(void) printf("Error - OCI_STILL_EXECUTE\n");
break;
case OCI_CONTINUE:
(void) printf("Error - OCI_CONTINUE\n");
break;
default:
break;
}
}
小さいLOBのOCIアクセスを改善するために、LOBデータをプリフェッチしてキャッシュする間にロケータもフェッチできます。これは内部LOB、一時LOBおよびBFILE
に適用されます。アプリケーションで実行できるステップは、次のとおりです。
セッション・ハンドルのOCI_ATTR_DEFAULT_LOBPREFETCH_SIZE
属性を設定します。この属性の値は、LOBロケータのデフォルトのプリフェッチ・データ・サイズを示します。これにより、セッション中にフェッチされる全LOBロケータのプリフェッチが可能になります。この属性のデフォルト値は0(LOBデータのプリフェッチなし)です。このオプションにより、アプリケーション開発者は定義ハンドルごとにプリフェッチLOBサイズを設定する必要がなくなります。この属性を設定するか、または(ステップ3で)OCI_ATTR_LOBPREFETCH_SIZE
を設定できます。
実行する文の準備ステップと定義ステップを実行します。
必要な場合は、定義ハンドルのOCI_ATTR_LOBPREFETCH_SIZE
属性を設定して、フェッチするLOBロケータのデフォルト・プリフェッチ・サイズを上書きできます。このオプション属性では、特定の列からフェッチされるロケータのプリフェッチ・サイズを制御できます。
OCI_ATTR_LOBPREFETCH_LENGTH
属性を、プリフェッチするLOBの長さおよびチャンク・サイズに設定します。
文を実行します。
個別のLOBロケータを指定してOCILobRead2()
またはOCILobArrayRead()をコールします。OCIによりプリフェッチ・バッファからデータが取得され、必要な文字変換が実行され、データがLOB読取りバッファにコピーされます(LOBセマンティクスは変更されません)。要求されたデータがプリフェッチ・バッファよりも大きい場合は、追加のラウンドトリップが必要になります。
OCILobGetLength2()
およびOCILobGetChunkSize()
をコールして、サーバーへのラウンドトリップなしで長さとチャンク・サイズを取得します。
プリフェッチ・サイズは、BLOB
およびBFILE
の場合はバイト数、CLOB
の場合は文字数であることに注意してください。
次のコード・フラグメントに、前述のステップを示します。
... ub4 default_lobprefetch_size = 2000; /* Set default size to 2K */ ... /* set lob prefetch attribute to session */ OCIAttrSet (sesshp, (ub4) OCI_HTYPE_SESSION, (void *)&default_lobprefetch_size, /* attribute value */ 0, /* attribute size; not required to specify; */ (ub4) OCI_ATTR_DEFAULT_LOBPREFETCH_SIZE, errhp); ... /* select statement */ char *stmt = "SELECT lob1 FROM lob_table"; ... /* declare and allocate LOB locator */ OCILobLocator * lob_locator; lob_locator = OCIDescriptorAlloc(..., OCI_DTYPE_LOB, ...); OCIDefineByPos(..., 1, (void *) &lob_locator, ..., SQLT_CLOB, ...); ... /* Override the default prefetch size to 4K */ ub4 prefetch_size = 4000; OCIAttrSet (defhp, OCI_HTYPE_DEFINE, (void *) &prefetch_size /* attr value */, 0 /* restricting prefetch size to be ub4 max val */, OCI_ATTR_LOBPREFETCH_SIZE /* attr type */, errhp); ... /* Set prefetch length attribute */ boolean prefetch_length = TRUE; OCIAttrSet( defhp, OCI_HTYPE_DEFINE, (dvoid *) &prefetch_length /* attr value */, 0, OCI_ATTR_LOBPREFETCH_LENGTH /* attr type */, errhp ); ... /* execute the statement. 4K of data for the LOB is read and * cached in descriptor cache buffer. */ OCIStmtExecute (svchp, stmthp, errhp, 1, /* iters */ 0, /* row offset */ NULL, /* snapshot IN */ NULL, /* snapshot out */ OCI_DEFAULT); /* mode */ ... oraub8 char_amtp = 4000; oraub8 lob_len; ub4 chunk_size; /* LOB chunk size, length, and data are read from cache. No round trip. */ OCILobGetChunkSize (svchp, errhp, lob_locator, &chunk_size); OCILobGetLength2(svchp, errhp, lob_locator, &lob_len ); OCILobRead2(svchp, errhp, lob_locator, NULL, &char_amtp, ...); ...
プリフェッチ・キャッシュの割当て: 記述子用のプリフェッチ・キャッシュ・バッファは、LOBロケータのフェッチ中に割り当てられます。割当てバッファ・サイズは、定義ハンドルのOCI_ATTR_LOBPREFETCH_SIZE
属性により決定されます。この属性のデフォルト値は、セッション・ハンドルのOCI_ATTR_DEFAULT_LOBPREFETCH_SIZE
属性の値で示されます。キャッシュ・バッファが割当済の場合は、必要に応じてサイズ変更されます。
次の2つのLOB APIの場合、ソース・ロケータにキャッシュされたデータがあると、宛先ロケータのキャッシュが割り当てられるかサイズ変更され、キャッシュ・データがソースから宛先にコピーされます。
OCILobAssign()
OCILobLocatorAssign()
記述子用に割り当てられたキャッシュ・バッファ・メモリーは、記述子自体が解放されるときに解放されます。
プリフェッチ・キャッシュの無効化: 記述子用のキャッシュは、ロケータを使用してLOBデータが更新されるときに無効化されます。これは、そのキャッシュがデータの読取りに使用されなくなり、ロケータでの次のOCILobRead()
コールでラウンドトリップが発生することを意味します。
次のLOB APIにより、使用された記述子用のプリフェッチ・キャッシュが無効化されます。
OCILobErase()
OCILobErase2()
OCILobTrim()
OCILobTrim2()
OCILobWrite()
OCILobWrite2()
OCILobWriteAppend()
OCILobWriteAppend2()
OCILobArrayWrite()
次のLOB APIにより、宛先LOBロケータ用のキャッシュが無効化されます。
OCILobAppend()
OCILobCopy()
OCILobCopy2()
OCILobLoadFromFile()
OCILobLoadFromFile2()
パフォーマンス・チューニング: プリフェッチ・バッファのサイズは、平均LOBサイズとクライアント側のメモリーに基づいて決定する必要があります。大量のデータがプリフェッチされる場合は、メモリーの可用性を確認する必要があります。データ・フェッチに伴うコストの方がサーバーへのラウンドトリップに伴うコストよりも大きいため、大きいLOBをプリフェッチする場合には、大幅なパフォーマンス向上は期待できない可能性があります。
このLOBプリフェッチ機能を活用できるように、LOBデータ・サイズを適正に考慮する必要があります。パラメータは、アプリケーション設計の一環です。そのため、パラメータ値の変更が必要になった場合は、アプリケーションを再作成する必要があります。
アップグレード: リリース11.1より前のサーバー、リリース11.1以降のサーバーに対するリリース11.1より前のクライアントには、LOBプリフェッチを使用できません。リリース11.1より前のサーバーをリリース11.1以降のクライアントに対して使用している場合、OCISetAttr()
からエラー、または、この機能がサーバーでサポートされていないという旨のエラー・メッセージが戻されます。
Oracle SecureFiles(Oracle Database 11gリリース1で導入されたSTORE AS SECUREFILE
オプションを使用するLOB)の場合、CREATE
TABLE
およびALTER
TABLE
文にSQLパラメータDEDUPLICATE
を指定できます。これにより、LOB列の複数行で同一の全LOBデータが同じデータ・ブロックを共有するように指定して、ディスク領域を節約できます。この機能をオフにするには、KEEP_DUPLICATES
を使用します。次の各オプションも、SECUREFILE
とともに使用されます。
パラメータCOMPRESS
では、LOB圧縮をオンにします。NOCOMPRESS
では、LOB圧縮をオフにします。
パラメータENCRYPT
では、LOB暗号化をオンにして、オプションで暗号化アルゴリズムを選択します。NOENCRYPT
では、LOB暗号化をオフにします。各LOB列には、他のLOB列または非LOB列の暗号化に関係なく、独自の暗号化仕様を設定できます。有効なアルゴリズムは、3DES168
、AES128
、AES192
およびAES256
です。
リリース11.1より前のLOBのパラダイムがデフォルトです。これは、オプションSTORE AS BASICFILE
でも明示的に設定されます。
SECUREFILE
機能とともに、次のSQL文、PL/SQLパッケージおよびOCI関数を使用します。