首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

ODAC 應用技巧 (二):BLOB/CLOB 大物件存取完整實戰

     編輯:Oracle 資料庫基礎

前言

Oracle 8 引入 LOB (BLOB、CLOB、NCLOB) 取代 LONG/LONG RAW,儲存機制為「表欄存 Lob Locator (指標),實體資料存獨立 LOB Segment」。ODAC 封裝 TOraQuery、TOraStoredProc 等組件支援 LOB 串流讀寫,但 DML/PLSQL 操作需遵循 EMPTY_LOB() 初始化 + RETURNING 子句 核心模式。本文完整演示查詢、DML 更新、存儲過程、參數綁定四大場景實戰代碼。

一、LOB 儲存機制速覽

  • Locator:表欄儲存的指標 (LOB Locator),指向 LOB Segment 實體資料。
  • 實體資料:存於 LOB Segment (可指定 Tablespace、Storage、Cache/NoCache)。
  • 讀取流程:SELECT 取得 Locator → 透過 Locator 串流讀取實體資料。
  • 寫入流程:UPDATE/INSERT 先用 EMPTY_BLOB()/EMPTY_CLOB() 初始化 Locator → RETURNING 取回新 Locator → 透過 Locator 寫入資料。

二、建表範例

CREATE TABLE clob_table (
  id   NUMBER PRIMARY KEY,
  name VARCHAR2(30),
  val  CLOB
) LOB (val) STORE AS (TABLESPACE lob_data CACHE);

三、場景一:TOraQuery 直接查詢讀取 LOB

// 讀取 CLOB 到字串/檔案
Query.SQL.Text := 'SELECT id, name, val FROM clob_table WHERE id = :id';
Query.ParamByName('id').AsInteger := 1;
Query.Open;
if not Query.IsEmpty then
begin
  // 方式 1:直接取字串 (小資料)
  ShowMessage(Query.FieldByName('val').AsString);
  
  // 方式 2:串流存檔 (大資料)
  Query.FieldByName('val').AsCLOBLocator.SaveToFile('C:\temp\export.txt');
end;
ODAC 自動處理 Locator 串流讀取,AsString/AsCLOBLocator/AsBLOBLocator 統一介面。

四、場景二:DML 更新 LOB — 核心 EMPTY_LOB + RETURNING 模式

錯誤示範 (直接綁定值 → ORA-22275)

UPDATE clob_table SET name = :name, val = :val WHERE id = :id;  -- ❌ 缺少 Locator 初始化

正確 SQL 範本

UPDATE clob_table
SET name = :name,
    val  = EMPTY_CLOB()           -- 1. 初始化 Locator
WHERE id = :id
RETURNING val INTO :val;          -- 2. 取回新 Locator 供後續寫入

ODAC 代碼實作

Query.SQL.Text := 
  'UPDATE clob_table SET name = :name, val = EMPTY_CLOB() ' +
  'WHERE id = :id RETURNING val INTO :val';
Query.ParamByName('id').AsInteger := 1;
Query.ParamByName('name').AsString := 'Updated';
Query.ParamByName('val').ParamType := ptInput;  // 關鍵:標記為輸入參數 (寫入模式)
Query.ParamByName('val').AsCLOBLocator.LoadFromFile('C:\data\import.txt');
Query.ExecSQL;

五、場景三:存儲過程封裝 LOB 邏輯 (推薦企業級做法)

PL/SQL 定義

CREATE OR REPLACE PROCEDURE clob_table_update (
  p_id   IN  NUMBER,
  p_name IN  VARCHAR2,
  p_val  OUT CLOB   -- 必須為 OUT 參數接收 RETURNING Locator
) IS
BEGIN
  UPDATE clob_table
  SET name = p_name,
      val  = EMPTY_CLOB()
  WHERE id = p_id
  RETURNING val INTO p_val;  -- 將新 Locator 回傳給呼叫端
END;
/

ODAC 呼叫代碼

StoredProc.StoredProcName := 'clob_table_update';
StoredProc.Prepare;  // 解析參數元資料
StoredProc.ParamByName('p_id').AsInteger := 1;
StoredProc.ParamByName('p_name').AsString := 'From Proc';
StoredProc.ParamByName('p_val').ParamType := ptInput;  // 關鍵:OUT 參數但實際寫入 → ptInput
StoredProc.ParamByName('p_val').AsCLOBLocator.LoadFromFile('C:\data\import.txt');
StoredProc.ExecProc;

關鍵點:ParamType = ptInput 的邏輯

  • PL/SQL 定義為 OUT (接收 RETURNING Locator)。
  • ODAC 層面實際是「寫入資料到 Server」→ 設定 ParamType := ptInput。
  • 若為讀取 LOB (SELECT/RETURNING 給客戶端),則設定 ptOutput。

六、場景四:通用 DML 參數綁定 (dtBlob/dtMemo)

對於非 RETURNING 的簡單 INSERT/UPDATE,可直接使用標準參數型別,Oracle 自動轉換 LONG/LONG RAW 相容:

Query.SQL.Text := 'INSERT INTO clob_table (id, name, val) VALUES (:id, :name, :val)';
Query.ParamByName('id').AsInteger := 2;
Query.ParamByName('name').AsString := 'Direct';
Query.ParamByName('val').DataType := ftMemo;  // dtMemo 對應 CLOB
Query.ParamByName('val').AsString := 'Direct string content...';  // 自動轉換
Query.ExecSQL;
適用於中小資料量、無需串流控制的簡單場景。大物件、高併發、需事務控制 → 必須用場景二/三模式。

七、BLOB 二進位資料處理差異

操作CLOB (字元)BLOB (二進位)
Locator 介面AsCLOBLocatorAsBLOBLocator
串流讀取LoadFromFile / SaveToFile (文字模式)LoadFromFile / SaveToFile (二進位模式)
參數 DataTypeftMemo / dtMemoftBlob / dtBlob
EMPTY 函數EMPTY_CLOB()EMPTY_BLOB()

八、總結

ODAC LOB 存取核心在於 Locator 生命週期管理:EMPTY_LOB() 初始化 → RETURNING 取回 → ParamType := ptInput 寫入 / ptOutput 讀取。存儲過程封裝 (場景三) 實現邏輯內聚、參數模式固定、應用層簡潔,是企業級應用推薦模式。大物件務必使用串流介面 (LoadFromFile/SaveToFile) 避免記憶體溢位。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved