2011年12月24日 星期六

Access 97, ODBC, unixODBC, iODBC, mdbtools 問題處理記錄

今天處理 Microsoft Access Database 的問題就花上了一整天 ...

簡單介紹一下該死的 MS Access Database (*.mdb) 是微軟發展的資料庫引擎,從 Access 97 使用 Jet 3.5 版本,從 Access 2000 時則採用 Jet 4.0 版本。

可以在 DSN 時指定 Provider 參數 Provider=Microsoft.Jet.OLEDB.4.0 指定 Jet OLEDB 的版本。


而在 Unix 系統上大致上有多款 Jet Database Engine 的實作 (應該是反向工程而來的) ,譬如:


首先 mdbtools 是由 C 寫成,可讀取 Access 97 版本以上的 mdb 檔案,不過在編碼的部份有點問題,若 Access 97 內使用 Big5 ,似乎沒辦法順利透過 mdbtools 提供的 charset 環境變數來指定,程式碼中使用到 iconv 的環境變數有:

MDBICONV=UTF-8
MDB_JET3_CHARSET=Big-5

該 JET3_CHARSET 為資料庫編碼,MDBICONV 為內部編碼,但這個解法無效,頂多只能讀出 Table 以及各 Table 資料內的比數,但由於 Access DB 的開發人員相當蠢,直接用 Big5 編碼的字元當做 Table Name ,所以無效。

後來也嘗試使用 mdbtools 將讀取出的 Table Name 利用 mbstring convert encoding 試著從 Big5 轉為 UTF-8 ,但這條路也不通,但讀出的字元是 ASCII 沒錯 (should be Big-5),這部份不知道是否有長輩有解答 ?

但我想只要該 DB 內資料若使用 ASCII 或是 ISO8859-1 的話應該是可以運作順利。

Jackcess 主要由 Java 所寫成,目前看起來可靠度最高,但是不支援 Access 97 以下版本,除此之外其他的 Jet Database 都支援,程式碼內也有 junit 所寫成的單元測試,測試各種格式的資料庫版本,不過因為不支援 Access 97 ,所以沒有繼續嘗試,否則應該是很好的跨平台解決方案。



資料庫介面的部份可以透過 ODBC 或是 iODBC 或是 Windows 上的 COM 元件來建立 ADODB 連線來讀取 Access Database 的資料庫,也可透過 ActiveXObject 建立 ADODB 連線。

不幸的地方在於,Unix 上的 mdbtools 既然無法運作正確,再接著用 ODBC 指定 Driver 為 mdbtools 也無用了。 否則應該是可以透過下列方式連結:

// With DSN
$connection = odbc_connect("access_db",'','');

// For Windows, DSN-less
$connection = odbc_connect("Driver={Microsoft Access Driver (*.mdb)};Dbq=$mdbFilename", $user, $password);

不過 ODBC 的部份光是指定 mdbtools 連連線都有問題。


接著嘗試使用 Windows 7 64bit 建立連至 Access 97 mdb 檔案的 ODBC 連線,發現 Jet Database Engine 並不支援 64bit Windows 7 ,有看到大概的解法,但我嘗試過也不行:

C:\Windows\SysWow64\odbcad.exe

所以只好轉而裝個 Virutalbox Windows XP 建立 ODBC 連線,連線沒問題,但同樣也卡在編碼。

整個 Google 都快翻過來的沒看到任何可以對 Access *.mdb 指定 CodePage 或是 Charset 的方法,或是嘗試了完全無效。

總之嘗試了以下大概幾種:

* Windows PHP 內的 COM 元件建立 ADODB.Connection
* JScript 使用 ActiveXObject 建立 ADODB.Connection
* PHP odbc_connect 連線

這三種途徑在 Windows XP 32bit 上都可順利連線,取得資料表清單,但仍是有編碼問題。

也就是說,就算是用微軟自己的 JScript (CScript) 都沒辦法正確讀出字元

推測大概還有幾種解決方法:

- 使用 Access 2010 把 Access 97 轉為較新版本的 mdb。
- 使用 MySQL Migration Toolkit 轉匯入至 MySQL (不過在新版的 MySQL 內卻找不到 Migration Toolkit 了,是否有分割出來 ? )

但我想編碼的方式應該還是有辦法解決,只是時間上的問題罷了。XD