
從前的舊包袱:MySQL database 和 table 都是 latin1,資料裡面有big5中文。又因應 big5,所以會有許多的 escape char("\") 在裡面;如今 UTF-8 的趨勢,用 mysqldump 出來的資料,裡面有 big5 的 \,也有跳脫特殊資源的 \,用 iconv 或 piconv 把 dump 出來的文字檔轉成 UTF-8 之後,要塞進新的資料庫會出現一堆問題,不外乎是取代跳脫字元時的例外狀況。資料不多的狀況下還好辦,用人眼判斷即可。但是資料量達到數十萬筆甚至數百萬筆的時候,恐怕還是換個方法吧。
環境如下:
系統直接升級為 MySQL version 5
舊的資料庫 OLD_DB ,charset 是 latin1,裡面有一個 table 叫作 tbl, charset 亦為 latin1
my.cnf 裡面
[client] 中有設定 default-character-set = utf8
[mysqld] 中有設定 default-character-set = utf8 還有 skip-character-set-client-handshake
[mysql] 中有設定 default-character-set = utf8
寫一個像以下的 php 如下:
<?
$outputfile= "OUTPUT.sql";
$DB_HOST="localhost";
$DB_USER="testuser";
$DB_PASS="testpass";
$DB_DBNAME="OLD_DB";
$DB_TABLE="tbl";
$fp=fopen($outputfile, "w+");
if(!$fp){
echo "Can not open file for writing.\n";
exit;
}
$dbcon=mysql_connect($DB_HOST, $DB_USER, $DB_PASS);
mysql_query("SET NAMES latin1", $dbcon);
mysql_select_db($DB_DBNAME, $dbcon);
$sqlstr="select * from $DB_TABLE";
$rs=mysql_query($sqlstr, $dbcon);
$NAMESTR="SET NAMES utf8;\r\n\r\n";
fwrite($fp, $NAMESTR, strlen($NAMESTR));
while($rsrow=mysql_fetch_row($rs)){
$i_sqlstr="INSERT INTO $DB_TABLE VALUES(";
foreach($rsrow as $rid=>$rval){
$rsrow[$rid]=iconv("BIG5", "UTF-8", $rval);
if(strval($rid)=="0")
$i_sqlstr.="'".addslashes($rsrow[$rid])."'";
else
$i_sqlstr.=", '".addslashes($rsrow[$rid])."'";
}
$i_sqlstr.=");\r\n\r\n";
fwrite($fp, $i_sqlstr, strlen($i_sqlstr));
}
mysql_free_result($rs);
mysql_close($dbcon);
fclose($fp);
exit;
?>
執行這個 php 之後,會產生一個 OUTPUT.sql
匯入之前,先建好新的 database 和 table。記得新的 databae 和 table 都要以 utf8 為 default charset
然後就可以 mysql -u XXX -p < OUTPUT.sql
轉換為 UTF-8 的過程並不會比傳統 mysqldump 出來再 import 進去來得慢。
迴響