PHP 連接 Microsoft Access (.mdb/.accdb) 需透過 ODBC 驅動。PDO_ODBC 提供統一介面,但需正確配置 DSN、驅動版本、架構匹配(32/64 位)。本文提供完整配置步驟、連接代碼、常見錯誤解決。
| Access 版本 | 驅動下載 | 檔案副檔名 |
| Access 2007-2010 | Access Database Engine 2010 | .mdb, .accdb |
| Access 2013-2016 | Access Database Engine 2016 | .accdb |
| Access 2019/365 | Access Database Engine 2019/365 | .accdb |
關鍵:PHP 進程架構必須與驅動架構一致!
- 64 位 PHP + 64 位驅動 ✅
- 32 位 PHP + 32 位驅動 ✅
- 64 位 PHP + 32 位驅動 ❌ (常見錯誤)
PDO 連接代碼
<?php
/**
* PDO 連接 Access
* @param string $dbPath 絕對路徑,如 C:\data\db.mdb 或 /var/www/data/db.accdb
* @return PDO
*/
function connectAccess(string $dbPath): PDO {
if (!file_exists($dbPath)) {
throw new InvalidArgumentException("資料庫檔案不存在:{$dbPath}");
}
// 判斷副檔名選擇驅動
$ext = strtolower(pathinfo($dbPath, PATHINFO_EXTENSION));
$driver = ($ext === 'accdb')
? 'Microsoft Access Driver (*.mdb, *.accdb)' // ACE 12.0/16.0
: 'Microsoft Access Driver (*.mdb)'; // JET 4.0
$dsn = "odbc:Driver={$driver};Dbq={$dbPath};";
// 可選參數
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false, // 使用真實預處理
PDO::ATTR_PERSISTENT => false, // Access 不支援持久連線
];
try {
$pdo = new PDO($dsn, '', '', $options); // Access 無帳密
return $pdo;
} catch (PDOException $e) {
// 詳細錯誤診斷
$msg = $e->getMessage();
if (str_contains($msg, 'architecture mismatch')) {
throw new RuntimeException("架構不匹配:PHP 為 " . (PHP_INT_SIZE === 8 ? '64位' : '32位') . ",請安裝對應版本 Access 驅動。原始錯誤:{$msg}");
}
if (str_contains($msg, 'driver not found') || str_contains($msg, '未找到驅動程式')) {
throw new RuntimeException("ODBC 驅動未安裝或名稱錯誤。請確認已安裝 '{$driver}'。原始錯誤:{$msg}");
}
throw new RuntimeException("Access 連接失敗:{$msg}");
}
}
// 使用範例
try {
$pdo = connectAccess(__DIR__ . '/data.mdb');
$stmt = $pdo->query('SELECT * FROM users WHERE status = 1');
$users = $stmt->fetchAll();
echo "查詢到 " . count($users) . " 筆資料\n";
print_r($users);
} catch (Throwable $e) {
echo "錯誤:{$e->getMessage()}\n";
}
?>
ODBC 系統 DSN 配置(可選,較穩定)
- 開啟「ODBC 資料來源管理員」(64 位:
odbcad32.exe,32 位:C:\Windows\SysWOW64\odbcad32.exe)
- 「系統 DSN」頁籤 → 「新增」 → 選擇 Microsoft Access Driver (*.mdb, *.accdb)
- 資料來源名稱:
MyAccessDB,描述任意
- 選擇資料庫檔案路徑 → 確定
PHP 連接:
<?php
$pdo = new PDO('odbc:MyAccessDB', '', '', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
?>
常見錯誤與解決
| 錯誤訊息 | 原因 | 解決 |
SQLSTATE[IM002] ... Data source name not found | DSN 名稱錯誤、或 32/64 位 ODBC 管理員不匹配 | 確認 PHP 架構、用正確位數 ODBC 管理員建立 DSN、或改用無 DSN 連接字串 |
architecture mismatch between driver and application | PHP 64位 + 驅動 32位(或反過來) | 重新安裝匹配架構的 Access Database Engine。若需共存,用 /passive 參數安裝兩版 |
Could not find installable ISAM | 驅動版本過舊不支援 .accdb、或檔案損壞 | 安裝 ACE 12.0+ 驅動、確認檔案完整性 |
Disk or network error / 無法鎖定檔案 | 檔案被獨佔、權限不足、網路磁碟延遲 | 確保 PHP 執行身分有讀寫權限、關閉其他開啟該檔的程式、本地磁碟優先 |
Too many fields defined | 查詢欄位超過 255 個 (Access 限制) | 縮減 SELECT 欄位、或分表 |
最佳實踐建議
- 避免生產環境用 Access:Access 是桌面資料庫,不支援高併發、無完整事務、易損壞。請遷移至 SQLite / MySQL / PostgreSQL / SQL Server。
- 唯讀場景:若僅需讀取匯入,考慮先用工具 (Access、Python pandas、ETL) 匯出 CSV/JSON 再導入目標資料庫。
- 連線管理:Access 不支援連線池,每請求新建連線,查詢完立即
$pdo = null 關閉。
- 預處理語句:雖 Access 對參數化支援有限,仍建議用
PDO::ATTR_EMULATE_PREPARES => false 並使用 ? 佔位符。
- 編碼:Access 內部用 Unicode,PHP 讀取通常無亂碼;若遇中文亂碼,嘗試
PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8 (需 sqlsrv 驅動) 或在 DSN 加 ;Charset=UTF-8。
Linux 替代方案
# Ubuntu/Debian
sudo apt-get install mdbtools unixodbc unixodbc-dev php-odbc
# 配置 /etc/odbcinst.ini
[MDBTools]
Description=MDBTools Driver
Driver=/usr/lib/x86_64-linux-gnu/odbc/libmdbodbc.so
Setup=/usr/lib/x86_64-linux-gnu/odbc/libmdbodbc.so
FileUsage=1
CPTimeout=5
CPReuse=5
# PHP 連接
$pdo = new PDO("odbc:Driver=MDBTools;Dbq=/path/to/file.mdb;", '', '');
限制:MDBTools 僅支援 .mdb (JET),不支援 .accdb (ACE);效能差、功能不全,僅適合一次性遷移腳本。
總結
PHP PDO 連接 Access 核心在於:架構匹配 (32/64位)、正確驅動名稱、檔案路徑權限。代碼簡單但環境配置易出錯。強烈建議將 Access 作為臨時資料來源,盡快遷移至標準伺服器級資料庫。
- 上一篇文章: PHP 跨瀏覽器文件下載中文亂碼完美解決方案
- 下一篇文章: PHP 訪問 Google Search API:Custom Search JSON API 完整整合指南
Copyright ©
程式碼之家 All Rights Reserved