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

PHP 連接 ODBC 資料源 (Access、SQL Server、DB2) 完整實戰:DSN 配置、預處理、編碼與效能優化

     編輯:PHP 相關知識

前言:ODBC 通用資料庫連接標準

ODBC (Open Database Connectivity) 讓 PHP 以統一介面存取異構資料庫 (Access、SQL Server、DB2、Oracle、MySQL、PostgreSQL 等)。適用於遷移專案、舊系統整合、異構查詢。現代新專案建議使用原生驅動 (PDO_SQLSRV、PDO_OCI、PDO_PGSQL) 以獲得更好效能與功能。

環境準備 (Linux)

# Ubuntu 22.04
sudo apt-get update
sudo apt-get install -y unixodbc unixodbc-dev php-odbc

# Microsoft ODBC Driver for SQL Server (支援 SQL Server 2012+)
curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
curl https://packages.microsoft.com/config/ubuntu/22.04/prod.list > /etc/apt/sources.list.d/mssql-release.list
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18

# Access (mdb/accdb) - 需 MDB Tools
sudo apt-get install -y mdbtools
# 或使用 UCanAccess (Java JDBC) 配合 PHP-Java Bridge

DSN 配置方式

方式適用場景範例
系統 DSN (系統層)多 PHP 進程共用、GUI 管理/etc/odbc.ini、odbcinst.ini
使用者 DSN單用戶、無 root 權限~/.odbc.ini
無 DSN (DSN-less)部署簡單、版本控管連線字串直接在 PHP 程式碼建構連線字串

DSN-less 連線字串範例

<?php
// Microsoft Access (.mdb/.accdb)
$dsn = "Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq=" . realpath('data.accdb') . ";";

// SQL Server (ODBC Driver 18)
$dsn = "Driver={ODBC Driver 18 for SQL Server};Server=192.168.1.100,1433;Database=mydb;Encrypt=yes;TrustServerCertificate=no;";

// PostgreSQL (psqlODBC)
$dsn = "Driver={PostgreSQL Unicode};Server=127.0.0.1;Port=5432;Database=mydb;";

// MySQL (MySQL ODBC)
$dsn = "Driver={MySQL ODBC 8.0 Unicode Driver};Server=127.0.0.1;Port=3306;Database=mydb;Charset=utf8mb4;";

PHP ODBC 基本操作

<?php
$dsn = "Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq=" . realpath('data.mdb');
$conn = odbc_connect($dsn, '', '', SQL_CUR_USE_ODBC); // 游標類型
if (!$conn) die("Connection failed: " . odbc_errormsg());

// 1. 執行無結果集 SQL (INSERT/UPDATE/DELETE/DDL)
$sql = "INSERT INTO products (name, price) VALUES (?, ?)";
$stmt = odbc_prepare($conn, $sql);
$params = ['Widget', 19.99];
if (!odbc_execute($stmt, $params)) {
    echo "Execute failed: " . odbc_errormsg($stmt);
}

// 2. 查詢結果集
$sql = "SELECT id, name, price FROM products WHERE price > ? ORDER BY price DESC";
$stmt = odbc_prepare($conn, $sql);
odbc_execute($stmt, [10.00]);

// 逐行處理 (記憶體友善)
while (odbc_fetch_row($stmt)) {
    $id = odbc_result($stmt, 'id');
    $name = odbc_result($stmt, 'name');
    $price = odbc_result($stmt, 'price');
    echo "$id | $name | $price\n";
}

// 3. 取得欄位中繼資料
$cols = odbc_num_fields($stmt);
for ($i = 1; $i <= $cols; $i++) {
    echo "Column $i: " . odbc_field_name($stmt, $i) . " (" . odbc_field_type($stmt, $i) . ")\n";
}

odbc_free_result($stmt);
odbc_close($conn);

進階:預處理語句與參數綁定

<?php
$conn = odbc_connect($dsn, 'user', 'pass', SQL_CUR_USE_ODBC);

// odbc_prepare + odbc_execute 為預處理 (驅動支援度不一)
$stmt = odbc_prepare($conn, "SELECT * FROM orders WHERE customer_id = ? AND order_date >= ?");
$params = [12345, '2024-01-01'];
if (odbc_execute($stmt, $params)) {
    // 處理結果
    while (odbc_fetch_array($stmt)) { /* ... */ }
} else {
    // 錯誤處理
    $err = odbc_error($conn);
    $msg = odbc_errormsg($conn);
    throw new RuntimeException("ODBC Error [$err]: $msg");
}

編碼處理策略

  • Access:舊版 .mdb 通常為系統預設編碼 (Big5/GBK/CP1252),需 iconv('BIG5', 'UTF-8', $val)。
  • SQL Server:ODBC Driver 17+ 預設 UTF-8,資料庫欄位 NVARCHAR 存 Unicode,無需轉碼。
  • 統一策略:資料庫層存 UTF-8,PHP 端統一 SET NAMES utf8mb4 (MySQL) 或依賴驅動自動轉碼。

效能優化與連線池

優化說明
SQL_CUR_USE_ODBC強制使用 ODBC 游標管理器,解決部分驅動 odbc_num_rows 回傳 -1 的問題
持久連線odbc_pconnect() 重用連線,適用 CLI 長運行/高頻請求,注意進程分叉後共用連線問題
批次操作關閉自動提交 odbc_autocommit($conn, false),批次執行後 odbc_commit()
只選需要欄位避免 SELECT *,減少網路傳輸與 ODBC 驅動轉換開銷
連線池 (PHP-FPM)ODBC 無原生連線池,建議使用 ProxySQL 或 PgBouncer (PostgreSQL) 代理

常見錯誤對照

錯誤代碼/訊息原因解決
IM002 Data source name not found驅動未安裝、DSN 名稱錯誤、32/64 位不匹配確認 odbcinst -q -d 列出驅動、PHP 與驅動位數一致
HY000 General errorSQL 語法錯誤、權限不足、資料類型不符啟用 odbc_errormsg() 取得詳細訊息
01004 String data right truncated欄位長度不足調整資料庫欄位長度或截斷資料
08S01 Communication link failure網路中斷、防火牆、Server 端逾時檢查網路、調整 ConnectionTimeout、啟用重連邏輯

完整封裝 Library (PDO 風格介面、自動重連、查詢建構器) 見 GitHub。

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