Linux0911 2006-1-22 06:13 AM
原 LATIN1 資料庫導入 GBK 字元集資料庫的 PHP 小程序源代碼
[url]http://www.enhand.net/blog.php?id=84[/url]
題外話:Mysql 版本 4.1.12,我用 phpMyAdmin2.6.2 可以正常顯示 gbk 字元集表中的內容,卻不能正常顯示原 latin1 字元集表中的內容(亂碼)。用 phpMyAdmin2.2.2 就剛好相反,可以正常顯示原 latin1 字元集表中的內容,卻不能正常顯示 gbk 字元集表中的內容(亂碼)。所以只好兩個版本都裝了。
php 存取 gbk 字元集的資料庫,需要在操作語句前加入如下語句,指定字元集,如果不指定,預設為 latin1。
mysql_query("SET NAMES gbk",$server_gbk);
不知道可以不可以改變 php 存取 mysql 的預設字元集?不需要每次訪問 Mysql 都要指定字元集,很麻煩。
正 文:
在 MySql 4.1 之後的版本支援 gbk, gb2312 等字元集,為方便 Jsp 不需經過代碼轉換直接存取 Mysql 資料庫(GBK 字元集),需要將原 LATIN1 字元集(4.1 之前的預設字元集)資料庫轉換為 gbk 字元集。
在 /usr/local/mysql/bin/mysql 通過命令方式下,或者使用 2.6.2 以上版本的 phpMyAdmin 建立一個新的 GBK 字元集資料庫,再使用 phpMyAdmin 導出腳本功能,導出表結構的腳本,會發現庫腳本中指定字元集 DEFAULT CHARSET=latin1。
CREATE TABLE MyTable (
……
(字段定義)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
將表結構腳本中 latin1 替換為 gbk,如下:
CREATE TABLE MyTable (
……
(字段定義)
) ENGINE=MyISAM DEFAULT CHARSET=gbk;
利用改了字元集的表結構在新的 GBK 字元集資料庫中建立相應表,於是您就擁有了與原 latin1 字元集資料庫結構完全一直的 gbk 資料庫。
或者更簡單的方法,直接使用 phpMyAdmin2.6.2 複製一個相同的資料庫(只複製結構,不複製數據),再使用 phpMyAdmin2.6.2 的「操作」功能,將新的資料庫和表的字元集都轉換為 gbk。
剩下的工作就是需要將原 Latin1 字元集資料庫中的數據導入到新的 GBK 字元資料庫中。這個工作可以用一個 php 小程序來完成。
假定原 latin1 字元集的資料庫名:db_latin1,新的 gbk 字元集的資料庫名:db_gbk,php 程序調用方式:togbk.php?tab=MyTable,轉換表 MyTable 的數據。
<?
set_time_limit(3600);
if(!$tab){
echo "沒有指定表名稱 tab=????";
exit;
}
$server_gbk =mysql_connect('localhost','root','password');
mysql_select_db('db_ gbk',$server_gbk);
mysql_query("SET NAMES gbk",$server_gbk);
$server_latin1 =mysql_connect('localhost','root','password');
mysql_select_db('db_latin1',$server_latin1);
mysql_query("SET NAMES latin1",$server_latin1);
$rpp = 2500;
$sql = "select count(1) from $tab";
$rst = mysql_query($sql,$server_latin1) or die('數據查詢出錯');
$row = mysql_fetch_array($rst);
mysql_free_result($rst) or die("無法清除換緩存?";
$rws = $row[0];
$tpg = ceil($rws/$rpp);
echo "原表一共 $rws 條記錄,分 $tpg 批處理<br>;";
flush();
for($p=0;$p<$tpg;$p++){
$sql = "select * from $tab limit " . $p*$rpp . "," . $rpp;
$rst = mysql_query($sql,$server_latin1) or die('數據查詢出錯');
$num = mysql_num_fields($rst);
while($row=mysql_fetch_array($rst)){
$sql = "insert into $tab values(";
for($i=0;$i<$num;$i++){
if($i==0)
$sql.=" '" . addslashes($row[$i]) . "'";
else
$sql.=",'" . addslashes($row[$i]) . "'";
}
$sql.=";";
mysql_select_db('db_gbk',$server_gbk);
mysql_query("SET NAMES gbk",$server_gbk);
if(!mysql_query($sql,$server_gbk)) echo $sql . mysql_error() . "<br>;";
mysql_select_db('db_latin1',$server_latin1);
mysql_query("SET NAMES latin1",$server_latin1);
}
mysql_free_result($rst) or die("無法清除?";
echo "第 " . ($p+1) . " 批完成<br>;";
flush();
}
mysql_close($server_latin1) or die("無法與伺服器斷開連接!";
mysql_close($server_gbk) or die("無法與伺服器斷開連接!";
?>;
<br>;
全部完成啦?
程序代碼:
[quote]先導出 mysql 3.x 的數據,在 mysql 4.0.x 上導入,然後從 4.0.x 上導出,在 4.1.x 上建立資料庫 create database mydb default character set latin1; 使用跟以前資料庫一樣的字元集,然後導入數據就 OK 了,我發現這個方式是最簡單省事的,有點奇怪的是 mysql 3.x 導出的數據直接導入到 4.1.x,即使設置成相同的字元集也是亂碼,所以必須經過 4.0.x 轉換一下[/quote]