OCI8 是 PHP 官方支援的 Oracle 資料庫擴充,提供高效能、功能完整的介面。本文示範使用 OCI8 函式風格 (Procedural) 連線 Oracle、執行查詢、逐行取得結果並輸出 HTML 表格的完整流程。程式碼已加入嚴格錯誤處理與資源釋放。
--with-oci8=instantclient,/path/to/instantclient (Linux) 或啟用 extension=oci8 (Windows)。ORACLE_SID、NLS_LANG (如 AMERICAN_AMERICA.AL32UTF8) 正確設定。<?php
declare(strict_types=1);
// 1. 設定 Oracle 環境 (需在連線前)
putenv('ORACLE_SID=ORASID');
putenv('NLS_LANG=AMERICAN_AMERICA.AL32UTF8'); // 關鍵:避免中文亂碼
// 2. 建立連線
$conn = oci_connect('username', 'password', '//host:1521/service_name');
if (!$conn) {
$e = oci_error();
die("連線失敗: {$e['message']}");
}
// 3. 解析 SQL 語句
$sql = 'SELECT full_name, email_address FROM email_info ORDER BY full_name';
$stid = oci_parse($conn, $sql);
if (!$stid) {
$e = oci_error($conn);
oci_close($conn);
die("SQL 解析失敗: {$e['message']}");
}
// 4. 執行查詢
$r = oci_execute($stid);
if (!$r) {
$e = oci_error($stid);
oci_free_statement($stid);
oci_close($conn);
die("查詢執行失敗: {$e['message']}");
}
// 5. 輸出 HTML 表格頭
echo '<table border="1" cellpadding="5" cellspacing="0">';
echo '<thead><tr><th>姓名</th><th>Email 地址</th></tr></thead>';
echo '<tbody>';
// 6. 逐行取得資料 (oci_fetch_array 預設回傳數字+關聯雙索引)
while (($row = oci_fetch_array($stid, OCI_ASSOC + OCI_RETURN_NULLS)) !== false) {
// htmlspecialchars 防 XSS,處理 NULL 顯示
$name = htmlspecialchars($row['FULL_NAME'] ?? '', ENT_QUOTES, 'UTF-8');
$email = htmlspecialchars($row['EMAIL_ADDRESS'] ?? '', ENT_QUOTES, 'UTF-8');
echo "<tr><td>{$name}</td><td>{$email}</td></tr>";
}
echo '</tbody></table>';
// 7. 釋放資源 (重要!避免連線洩漏)
oci_free_statement($stid);
oci_close($conn);
?>
| 舊版 ORA_* 函式 (已移除) | 現代 OCI8 函式 | 說明 |
|---|---|---|
Ora_Logon() | oci_connect() / oci_pconnect() | 建立連線,支援 Easy Connect 字串 |
Ora_Open() | 不需要,oci_parse() 直接回傳 statement | |
Ora_Parse() | oci_parse() | 預處理 SQL |
Ora_Exec() | oci_execute() | 執行 statement |
Ora_Fetch_Into() | oci_fetch_array() / oci_fetch_assoc() / oci_fetch_object() | 取得下一行,支援多種模式 |
Ora_Close() | oci_free_statement() | 釋放 statement 資源 |
Ora_Logoff() | oci_close() | 關閉連線 |
Ora_Error() | oci_error() | 取得錯誤資訊陣列 |
Ora_Commit() | oci_commit() | 提交交易 |
Ora_Rollback() | oci_rollback() | 回滾交易 |
// 參數化查詢 (防注入、提升解析重用)
$sql = 'SELECT * FROM email_info WHERE department = :dept AND created_at > :date';
$stid = oci_parse($conn, $sql);
// 繫結 PHP 變數到 Oracle 佔位符
oci_bind_by_name($stid, ':dept', $deptVar);
oci_bind_by_name($stid, ':date', $dateVar, 20); // 長度建議指定
// 執行
oci_execute($stid);
// 重複執行不同參數時,無需重新 parse,直接改變 $deptVar/$dateVar 再 execute
// 這就是「軟解析」重用的威力
原生 OCI8 函式較冗長,建議封裝或使用社區庫:
OracleDB 類別封裝 connect, query, fetchAll, execute, beginTransaction, commit, rollback 等方法。NLS_LANG=.AL32UTF8 (或資料庫字符集對應值),並在 PHP 檔案存為 UTF-8 無 BOM。FULL_NAME),使用 OCI_ASSOC 時鍵值為大寫。oci_fetch_array(..., OCI_RETURN_NULLS) 才會在陣列中包含 NULL 鍵,否則會略過。oci_fetch_array 取得 LOB 描述子,再呼叫 ->load() 或 ->read()。oci_pconnect 長連線,或 CLI 模式下定期 oci_ping($conn) 心跳。OCI8 是 PHP 連接 Oracle 的標準方式,提供完整的預處理、繫結變數、LOB 處理、交易控制等企業級功能。本文示範了從連線、查詢、取值、輸出到資源釋放的標準流程,並對照了已移除的舊版 ORA_* 函式。掌握 oci_parse → oci_bind_by_name → oci_execute → oci_fetch_array 這條主線,即能應對絕大多數 Oracle 開發場景。