単純型のフィールドと異なり、巨大なデータを格納できるフィールド型としてOracleは以下の型を用意しています

  1. Long型 / Long raw 型
    Oracle7以前でも使えます。最大2GBのデータを、テーブルのデータ領域に他のカラムと一緒に格納します。したがって、SELECT文によるテーブルスキャンは相当に遅くなる可能性があります。
  2. Clob / Blob型
    Oracle8以降で使えます。最大4GBのデータを格納できます。データはテーブルデータとは別の領域に格納され、テーブルのデータ領域にはその領域へのポインタのみが格納されるため、SELECT
    * FROM Table
    ..によるテーブルスキャンのパフォーマンスは、Clob/Blobデータのデータサイズの影響を受けません。その代わりに、データアクセスの手順が少し煩雑になりました。
  3. BFile型 – Oracle8以降。データベースサーバ上のファイルを読み出せます

これらの項目(広義のBlob(Binary Large
Object)型を扱う場合には、アプリケーション設計を誤ると、大量のデータを一度にサーバから取得することになり、絶望的に長い処理時間を要します。一般的に言って、広義のBlobカラムについて、一度にデータを丸々取得すべきレコードは最大一件まででなければ、実用的なパフォーマンスが得られないと考えてよいでしょう。

一方、Oracle8から導入されたClob/ Blob/ BinFile
型を利用する場合は、レコードの先読みが可能で、パフォーマンスの向上が期待できます。その代わり、Clob/
Blob/
BinFile型のカラムは、通常の単純型のフィールドのようにFieldメソッドを用いて簡単にアクセスすることができず、TLOBLocatorオブジェクトを介して間接的にアクセスしなければなりません。


Long / Long raw 型の使用

制限事項

Long/Long raw 項目自体は、決してバッファに読み込まれず、
Field関数を実行したときに初めてサーバからデータが取得されます。

また、Long型/Long raw型のフィールドを含むSELECT文を実行した場合、
TOracleQueryは、最大1件分のレコードしかバッファに読み込みません。すなわち
ReadBufferプロパティの設定は無視され、レコードの先読みが行われなくなります。

Long/Long raw 型の output
変数はサポートされません。SELECT文を使った方がよいでしょう。input/output変数として宣言した上で、予め十分な容量のメモリを確保してこれを
input
に与えた時に限り、変数からoutputを取得可能です。詳しくはDOAのヘルプを読み込むなどしてください。

使用例

以下に、Long項目を取得するプログラムの例を示します

  // OracleQuery1.SQL =
  //   SELECT Memo FROM TestTable
  //   WHERE MemoId = :MemoId
  try
    with OracleQuery1 do
    begin
      SetVariable('MemoId', MemoId);
      Execute;  
      RichEdit1.Lines.Text := Field('Memo').AsString;
    end;
  except
    on E:EOracleError do ShowMessage(E.Message);
  end;

上記の例のように、文字列フィールドとしてアクセスすることができますが、最も高速にアクセスできるのは、以下のようにVarArrayLock/VarArrayUnlockを用いてデータを(array
of
byteとして)読み込んだバッファのポインタを得る方法です。(VarArrayLock/VarArrayUnlockについてはDelphiのヘルプを参照してください)

  // SelectEmpPictureQuery.SQL =
  // select picture from emp
  // where empno = :empno
  try
    with SelectEmpPictureQuery do
    begin
      SetVariable('EMPNO', Emp.EmpNo);
      Execute;
      Picture := Field('PICTURE');                 //PictureはVariant型です
      Size    := VarArrayHighBound(Picture, 1) + 1; //Variantのサイズを取得
      Ptr     := VarArrayLock(Picture);      //Variantデータへのポインタを取得
      try
          WriteFile('Employee.gif', Ptr^, Size); //ポインタとサイズを用いてアクセスできます
      finally
          VarArrayUnlock(Picture);               //VarArrayLockと対にして使います
        end;
    end;
  except
    on E:EOracleError do ShowMessage(E.Message);
  end;

データを更新するには、以下のようにパラメータ付きクエリーを用います。SetVariableでstring型データを渡すこともできますが、SetLongVariableが効率よい方法です。INSERTの場合も下記と同様です。

  //OracleQuery1.SQL = 
  //  UPDATE TestTable
  //  SET BinaryData = :BinaryData
  //  WHERE TableKey := TableKey
  try
    with OracleQuery1 do begin
      SetVariable('TableKey', TableKey);
      SetLongVariable('BinaryData', WavBuffer, WavLength);
      Execute;
    end;
  except
    on E: EOracleError do showmessage(E.Messasge);
  end;


CLob/ Blob /BFile (LOB)型の使用

DOAでOracle8が導入したBlob型にアクセスするには、TLOBLocator
オブジェクトを利用します。まず、SELECTしたLOBカラムには、TOracleQuery.LOBFieldメソッドでアクセスします。TLOBLocatorはTStreamを継承しているので、Seek/Read/Writeなどのメソッドが利用できます。

  var LOB: TLOBLocator;
      Buffer: array[0..99] of Byte;
  begin
    // select lobcolumn from lobtable where id = 1
    with LOBQuery do
    begin
      Execute;
      LOB := LOBField('lobcolumn');
      if not LOB.IsNull then
      begin
        LOB.Seek(-100, soFromEnd);
        LOB.Read(Buffer, 100);
      end;
    end;
  end;

NULL値がセットされている既存レコードのLOBカラムを更新する場合や、新規レコードを挿入する場合には、以下のようにLOBを新規作成する必要があります。

  var LOB: TLOBLocator;
      Buffer: array[0..99] of Byte;
  begin
    // LOBQuery.SQL = 
    // INSERT INTO lobtable (id, lobcolumn) VALUES (:id, empty_blob()) 
    //   RETURNING lobcolumn INTO :lobcolumn
    with LOBQuery do
    begin
      SetVariable('id', 1);
      // 新規BLOBを作成し
        // RETURNINGで返される変数にバインドする
      LOB := TLOBLocator.Create(Session, otBLOB);
      try
        SetComplexVariable('lobcolumn', LOB);
        Execute;
        // 挿入してからTStreamのメソッドでLOBを更新する
        LOB.Write(Buffer, 100);
      finally
        LOB.Free;
      end;
    end;
  end;

以上、簡単に紹介しましたが、詳細については、TOracleQuery.Variables ,
TOracleQuery.SetComplexVariable, TLOBLocatorなどを中心にDOAのヘルプを参照してください。