PHP 通過 PDO_ODBC 驅動連接 Access (.mdb/.accdb) 文件,適合遷移舊系統、讀取桌面數據庫導出數據等場景。需 Windows 環境配置 ODBC 驅動程序。
<?php
try {
// 構造 DSN 連接字符串
$dsn = "odbc:driver={Microsoft Access Driver (*.mdb)};dbq=" . getcwd() . "\db.mdb";
// 創建 PDO 實例
$db = new PDO($dsn);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully!\n";
// 測試查詢
$stmt = $db->query("SELECT * FROM test_table");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
print_r($row);
}
} catch (PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
?>
編輯 php.ini,確保以下擴展已啟用(去掉分號):
extension=pdo_odbc
extension=odbc
驗證:運行 php -m | grep -i odbc 或查看 phpinfo() 輸出。
關鍵注意:PHP 進程位數必須與 ODBC 驅動位數一致(32位 PHP 需 32位驅動,64位 PHP 需 64位驅動)。
<?php
// .mdb 文件 (Access 2003及以前)
$dsn = "odbc:driver={Microsoft Access Driver (*.mdb)};dbq=C:\path\db.mdb";
// .accdb 文件 (Access 2007+)
$dsn = "odbc:driver={Microsoft Access Driver (*.mdb, *.accdb)};dbq=C:\path\db.accdb";
// 帶密碼的數據庫
$dsn = "odbc:driver={Microsoft Access Driver (*.mdb)};dbq=C:\path\db.mdb;pwd=your_password";
// 使用系統 DSN (預先在 ODBC 管理器配置)
$dsn = "odbc:dsn=my_access_dsn;uid=admin;pwd=password";
// 絕對路徑最佳實踐
$dbPath = realpath(__DIR__ . '/data/db.mdb');
$dsn = "odbc:driver={Microsoft Access Driver (*.mdb)};dbq={$dbPath}";
<?php
class AccessDB {
private $pdo;
public function __construct(string $dbPath, string $password = '') {
$driver = pathinfo($dbPath, PATHINFO_EXTENSION) === 'accdb'
? 'Microsoft Access Driver (*.mdb, *.accdb)'
: 'Microsoft Access Driver (*.mdb)';
$dsn = "odbc:driver={$driver};dbq={$dbPath}";
if ($password) $dsn .= ";pwd={$password}";
$this->pdo = new PDO($dsn);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
}
public function query(string $sql, array $params = []): array {
$stmt = $this->pdo->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll();
}
public function execute(string $sql, array $params = []): int {
$stmt = $this->pdo->prepare($sql);
$stmt->execute($params);
return $stmt->rowCount();
}
public function getLastId(): string {
// Access 不支持 lastInsertId,需查詢 @@IDENTITY
return $this->pdo->query("SELECT @@IDENTITY")->fetchColumn();
}
}
// 使用示例
$db = new AccessDB(__DIR__ . '/data/test.mdb');
// 查詢
$users = $db->query("SELECT * FROM users WHERE age > ?", [18]);
// 插入
$affected = $db->execute("INSERT INTO users (name, age) VALUES (?, ?)", ['張三', 25]);
$newId = $db->getLastId();
// 更新
$db->execute("UPDATE users SET age = ? WHERE id = ?", [26, $newId]);
// 刪除
$db->execute("DELETE FROM users WHERE id = ?", [$newId]);
?>
| 錯誤現象 | 原因 | 解決方案 |
|---|---|---|
| could not find driver | pdo_odbc 擴展未啟用 | php.ini 啟用 extension=pdo_odbc,重啟 PHP |
| Data source name not found | 驅動名稱錯誤/未安裝 | 檢查驅動確切名稱:odbcad32.exe 驅動程序標籤查看 |
| Architecture mismatch | PHP 與驅動位數不匹配 | 安裝匹配位數驅動,或切換 PHP 版本 |
| General error: Unable to open database | 路徑錯誤/權限不足/文件被佔用 | 使用絕對路徑、檢查文件權限、關閉 Access 應用 |
| Optional feature not implemented | Access 驅動不支持某些 PDO 功能 | 避免使用預處理游標、事務嵌套等高級特性 |
<?php
echo "PHP 位數: " . (PHP_INT_SIZE === 8 ? '64位' : '32位') . "\n";
echo "ODBC 驅動列表:\n";
print_r(PDO::getAvailableDrivers());
// 查看已安裝 ODBC 驅動 (Windows)
exec('odbcad32.exe', $output);
print_r($output);
| PHP 版本 | Office 版本 | 需安裝驅動 | 備註 |
|---|---|---|---|
| 32位 | 32位 | 32位 Access Database Engine | 最佳匹配 |
| 64位 | 64位 | 64位 Access Database Engine | 最佳匹配 |
| 64位 | 32位 | 無法直接連接 | 需遷移至 32位 PHP 或使用中間層 |
| 32位 | 64位 | 32位 Access Database Engine | 可行,但 32位驅動需強制安裝 |
fgetcsv)或 PhpSpreadsheetPHP PDO 連接 Access 核心在於:正確安裝匹配位數的 ODBC 驅動、構造準確的 DSN 字符串、處理驅動特有的限制(如無 lastInsertId)。生產環境建議盡早遷移至標準關係型數據庫(MySQL/PostgreSQL/SQL Server)。