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

PHP 呼叫 Oracle 預存程序完整實戰:從建表、建 Procedure 到 OCI8 參數綁定與異常處理

     編輯:Oracle 資料庫基礎

PHP 搭配 Oracle 開發企業級應用時,**預存程序 (Stored Procedure)** 是封裝業務邏輯、提升效能、強化安全的關鍵利器。本文以完整可運行的程式碼,示範從資料庫端建立 Procedure、到 PHP 端使用 **OCI8 擴展** 進行參數綁定、執行與結果處理的全流程最佳實踐。

資料庫端準備

1. 建立測試表與資料


CREATE TABLE test_proc (
  id   NUMBER(16) NOT NULL PRIMARY KEY,
  name VARCHAR2(30) NOT NULL
);

INSERT INTO test_proc VALUES (5, 'PHP_book');
COMMIT;

2. 建立帶 IN/OUT 參數的預存程序


CREATE OR REPLACE PROCEDURE proc_test (
  p_id   IN OUT NUMBER,      -- 輸入查詢條件,亦可回傳異動後的值
  p_name OUT VARCHAR2       -- 輸出查詢結果
) AS
BEGIN
  SELECT name INTO p_name
  FROM test_proc
  WHERE id = p_id;           -- 此處 p_id 為 5
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    p_name := 'NOT_FOUND';
  WHEN OTHERS THEN
    p_name := 'ERROR:' || SQLERRM;
END proc_test;
/

PHP 端完整實作 (OCI8)


= Procedure 定義)

// ========== 4. 解析 SQL 呼叫語句 ==========
// 語法: BEGIN 程序名(:參數1, :參數2); END;
// 冒號表示位置佔位符,名稱建議與 Procedure 參數名一致
$sql = "BEGIN proc_test(:id, :name); END;";
$stmt = oci_parse($conn, $sql);
if (!$stmt) {
    $e = oci_error($conn);
    die("Parse failed: " . $e['message']);
}

// ========== 5. 綁定參數 (關鍵步驟) ==========
// oci_bind_by_name(resource $statement, string $param_name, mixed &$variable, int $maxlength = -1, int $type = SQLT_CHR)
// $maxlength: OUT 參數必須指定足夠長度,否則截斷或報錯
oci_bind_by_name($stmt, ':id',   $id,   16);   // NUMBER(16) -> 長度 16 足夠
oci_bind_by_name($stmt, ':name', $name, 30);   // VARCHAR2(30) -> 長度 30

// ========== 6. 執行 ==========
$r = oci_execute($stmt);
if (!$r) {
    $e = oci_error($stmt);
    die("Execute failed: " . $e['message']);
}

// ========== 7. 取得 OUT 參數值 ==========
// 執行後,$name 變數已被 Oracle 回寫
echo "Name is: $name
\n"; // ========== 8. 清理資源 ========== oci_free_statement($stmt); oci_close($conn); ?>

關鍵技術細節深度解析

環節核心要點
連線函式oci_connect (非持久) vs oci_pconnect (持久,Apache Prefork MPM 下慎用,易超連線數)
SQL 語法必須包裹在 BEGIN ... END; 區塊,參數前加冒號 :param
參數模式IN: 僅輸入;OUT: 僅輸出 (需初始化變數);IN OUT: 雙向 (需給初始值)
綁定長度OUT/IN OUT 參數 **必須指定 $maxlength** >= 定義長度,否則 ORA-06502 數值/字串截斷錯誤
資料類型對應NUMBER → PHP int/float/string;VARCHAR2 → PHP string;DATE → PHP string (需 NLS_DATE_FORMAT) 或 OCI_B_DATE
例外處理Procedure 內部 EXCEPTION WHEN OTHERS 回傳錯誤碼/訊息至 OUT 參數,避免中斷 PHP 流程

進階場景:呼叫 Function 並取得 RETURN 值


-- DB 端
CREATE OR REPLACE FUNCTION func_get_name(p_id NUMBER) RETURN VARCHAR2 AS
  v_name VARCHAR2(30);
BEGIN
  SELECT name INTO v_name FROM test_proc WHERE id = p_id;
  RETURN v_name;
EXCEPTION WHEN NO_DATA_FOUND THEN RETURN 'NOT_FOUND';
END;
/

-- PHP 端
$sql = "BEGIN :ret := func_get_name(:id); END;";
$stmt = oci_parse($conn, $sql);
$ret = '';
oci_bind_by_name($stmt, ':ret', $ret, 30);   // RETURN 值視為 OUT 參數
oci_bind_by_name($stmt, ':id',  $id,  16);
oci_execute($stmt);
echo "Function returned: $ret";

常見錯誤與排查

  • ORA-06550 / PLS-00306: 參數數量/類型/順序不匹配 → 核對 PHP 綁定順序與 Procedure 定義。
  • ORA-01008: not all variables bound: 有參數未綁定 → 檢查 oci_bind_by_name 是否漏寫。
  • ORA-06502: numeric or value error: OUT 參數長度不足 → 增加 $maxlength。
  • ORA-24374: define not done before fetch: 呼叫 Function 時 RETURN 參數未綁定 → 必須綁定 :ret。

最佳實務清單

  1. **集中管理連線字串**:放入環境變數或獨立配置檔,勿硬編碼。
  2. **使用連線池**:生產環境搭配 Oracle DRCP (Database Resident Connection Pool) 或 PHP-FPM + oci_pconnect 謹慎調優。
  3. **參數化查詢**:杜絕字串拼接 SQL,所有輸入皆走 oci_bind_by_name,防 SQL 注入。
  4. **錯誤碼標準化**:Procedure 統一回傳 p_code, p_msg OUT 參數,PHP 端統一處理。
  5. **資源釋放**:oci_free_statement + oci_close 必須成對出現,避免洩漏。

掌握 OCI8 參數綁定機制,讓 PHP 與 Oracle 預存程序無縫協作,是構建高效、安全、可維護企業級應用的關鍵基石。

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