首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

PHP PDO 讀取 Oracle CLOB 大字段分塊讀取方案

     編輯:Oracle 資料庫相關知識

問題背景

PDO 直接 SELECT clob_col FROM table 當字段超過驅動/內存限制時會截斷或報錯,需分片讀取並拼接。

方案:存儲過程 + PHP 循環調用

1. 創建分片讀取存儲過程

CREATE OR REPLACE PROCEDURE get_clob(
  t_name   IN  VARCHAR2,   -- 表名
  f_name   IN  VARCHAR2,   -- 字段名
  u_id     IN  INTEGER,    -- 主鍵值
  l_pos    IN  INTEGER,    -- 起始位置 (1-based)
  l_amt    IN  BINARY_INTEGER, -- 讀取長度
  ret_val  OUT VARCHAR2    -- 返回片段
) IS
  v_clob   CLOB;
  v_buf    VARCHAR2(3999);
  v_amt    BINARY_INTEGER;
BEGIN
  EXECUTE IMMEDIATE 'SELECT '||f_name||' FROM '||t_name||' WHERE id=:1'
    INTO v_clob USING u_id;
  v_amt := l_amt;
  DBMS_LOB.READ(v_clob, v_amt, l_pos, v_buf);
  ret_val := v_buf;
END get_clob;
/

2. PHP 端分片拼接邏輯

$pdo = new PDO('oci:dbname=//host:1521/sid', $user, $pass);

// 1. 先查總長度
$stmt = $pdo->prepare("SELECT LENGTH(content) AS len FROM test WHERE id = :id");
$stmt->execute(['id' => $id]);
$total = (int)$stmt->fetchColumn();

// 2. 循環讀取拼接
$content = '';
$chunk = 2500;          // 每片長度 (<= 32767)
$start = 1;
while ($start <= $total) {
  $ret = '';
  $sql = "BEGIN get_clob(?,?,?,?,?,?); END;";
  $st = $pdo->prepare($sql);
  $st->bindParam(1, 'test',      PDO::PARAM_STR, 100);
  $st->bindParam(2, 'content',   PDO::PARAM_STR, 100);
  $st->bindParam(3, $id,         PDO::PARAM_STR, 100);
  $st->bindParam(4, $start,      PDO::PARAM_STR, 100);
  $st->bindParam(5, $chunk,      PDO::PARAM_STR, 100);
  $st->bindParam(6, $ret,        PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 5000);
  $st->execute();
  $content .= $ret;
  $start += $chunk;
}

$pdo = null;
echo $content;  // 完整 CLOB 內容

關鍵點

  • DBMS_LOB.READ 支援任意位置/長度讀取,避免一次性載入巨大 LOB。
  • 動態 SQL (EXECUTE IMMEDIATE) 實現表/字段參數化,通用性強。
  • PHP 端 PARAM_INPUT_OUTPUT 接收 OUT 參數,5000 需大於片段長度。
  • 片段長度建議 2000~4000,平衡網絡往返與內存佔用。

替代方案

  • Oracle 12c+ TO_LOB / DBMS_LOB.CONVERTTOBLOB 配合 SELECT ... FROM TABLE(CAST(...))。
  • OCI8 擴展原生 oci_fetch_array + OCI_LOB->read() 流式讀取。
  • 應用層分頁查詢 DBMS_LOB.SUBSTR(clob, 4000, offset) 避免存儲過程。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved