最近換成使用 MySQL 4.1 的人越來越多了,在許多地方也看到了哀嚎聲四起,遇到的狀況不外乎是原本的資料突然都變成不正常了,所以在這邊提供正解。
事實上這個問題不光是使用 UTF8 會有,照理說使用其他語系也會有相同的問題,例如如果我們原本用 GB2312 來存資料,結果現在升級後應該也會有問題。解決之道也很簡單:資料庫是什麼編碼,之後 Client 端程式就用什麼編碼和它溝通。
那要怎麼知道資料庫原本是什麼編碼呢?我在 commit 給 plog 中 adodb 的 patch 中包含了一段檢查 database encoding 的 code:
function _getDbDefaultEncoding($argDatabasename){ if (!$argDatabasename) { return false; } // We use a SHOW CREATE DATABASE command to // show the original SQL character set when DB was // created. $result = mysql_query("SHOW CREATE DATABASE $argDatabasename", $this->_connectionID); if (mysql_num_rows($result) < 0 ) { // The specified db name is wrong! return false; } $dbInfo = mysql_fetch_row($result); $pattern = '/40100 DEFAULT CHARACTER SET (w+) /'; if ( (preg_match($pattern, $dbInfo[1], $match) > 0) ) { return $match[1]; } return false; }
這個函式會檢查當初資料庫建立的編碼方式,並回傳回來,這樣可以確保我們不是冒然把 MySQL client 的 encoding 設定成 UTF-8 (這是目前看到大多數人的解法)。
接下來,在 SelectDB() 函式中,做以下修改:
function SelectDB($dbName) { $this->databaseName = $dbName; if ($this->_connectionID) { + $dbEncoding = + $this->_getDbDefaultEncoding($dbName); + if ($dbEncoding) { + mysql_query("SET NAMES $dbEncoding", + $this->_connectionID); + } return @mysql_select_db($dbName, $this->_connectionID); } else return false;
這樣應該不管原本的編碼為何,讀和寫都不會有問題;唯一要注意的是,如果你的 MySQL 不是 4.1 以上,有些指令並不支援,所以這段 patch 不適用;我也替 pLog 寫了一個 isSupportUtf8() 的 function call, 可以用來檢查是否是 4.1 以上的版本,不過就不再這邊多加贅述了。
P.S. 請注意,如果你沒有學過 PHP,請不要問我該怎麼加入這段程式碼。請尋求你所使用的軟體之開發者的協助。