星期一, 12月 20, 2004

成功 怒火 威力

成功 怒火 威力


以下為胡搞瞎搞測試,如果發生任何意外本人不負責低 ...

我一開始寫的網頁:
http://netlab.cse.yzu.edu.tw/~statue/freebsd/zh-tut/mysql.html

剛剛晚上睡不著,編了兩個資料庫在玩:

o 測試資料
成功 = a6 a8 a5 5c (5c 為特殊字元 '\')
怒火 = ab e3 a4 f5
威力 = ab c2 a4 4f

o CHARSET=latin1
mysql> show variables like 'character_set';
+---------------+--------+
| Variable_name | Value | +---------------+--------+
| character_set | latin1 |
+---------------+--------+
mysql> use test
mysql> create table tt ( tt varchar(20) );
mysql> insert into tt values ("成功"); // 判斷錯誤囉, 請按 "; 結束
mysql> insert into tt values ("成功\");
Query OK, 1 row affected (0.00 sec)
mysql> insert into tt values ("怒火");
mysql> select * from tt where tt = "威力";
+------+
| tt | +------+
| 怒火 |
+------+
1 row in set (0.00 sec)

o CHARSET=big5
如果編譯的時候有加 WITH_CHARSET=big5 WITH_XCHARSET=all
mysql> show variables like 'character_set';
+---------------+-------+
| Variable_name | Value | +---------------+-------+
| character_set | big5 |
+---------------+-------+
mysql> insert into tt values ("成功");
Query OK, 1 row affected (0.00 sec)
mysql> select * from tt where tt = "威力"; // 就不會產生錯誤。

o 影響
主要影響的部份還有 mysql-client, 以及相關的程式寫作, 例如 php.

後記之1:

由於必須將某個 MySQL 資料庫轉移到另一台機器發生的問題。

原機器上的 MySQL 以 latin1 作為資料庫編碼,另一個則是以 big5,

在使用 mysqldump 出來後,要匯入另一個資料庫就出事了 ~"~..

沒錯,無法匯入 .. 因為特殊中文字('\')的關係 ...

由於中文字與 mysql 的特殊字混雜,造成 escape 符號會同時出現在這兩個中

沒辦法用簡單的 script 來轉換,那時候想到的做法是:

寫程式找出特殊文字, 將它後面的 escape 幹掉.

不過同時,異想天開認為 escape 應該是進入前的判斷,其實資料庫本身

在 latin1 與 big5 間是沒有差別的吧?

因此直接關閉兩邊的資料庫,以檔案拷貝的方式傳送過來,開啟資料庫 ...


成功耶!


不過相關的 php 程式也都需要重新修改過了.


PS. 以其他的編碼開啟資料庫
/usr/local/bin/mysqld_safe --default-character-set=latin1
或是編輯 /usr/local/etc/my.cnf
-- my.cnf --
[client]
default-character-set=latin1

[mysqld]
default-character-set=latin1
-- my.cnf --

但是如果沒有 --with-charset=big5 或是 --with-extra-charsets=all 時,
是無法從 latin1 直接轉成 big5 的:

mysql: File '/usr/local/share/mysql/charsets/big5.conf' not found (Errcode: 2)
mysql: Character set 'big5' is not a compiled character set and is not
specified in the '/usr/local/share/mysql/charsets/Index' file

後記之2:

主要是 php 程式方面的改變.

magic_quotes_gpc 是個非常芭樂的東西, 因為他會將某些中文字多加 '\' 造成
無法將資料送進資料庫. 他主要是呼叫 addslashes() 來加 '\' 的.

addslashes() 的好意是能將對於 database 的特殊字元多加 '\' 以利送進資料
庫,但是問題是無法判斷中文.

所以直接把 magic_quotes_gpc 關掉吧, 找尋可以加 '\' 又可以判斷中文的.

於是發現在 mysql_client_encoding() 的結果為 big5 的情況下,
使用 mysql_escape_string() 可以正確的處理中文, 收工.

http://tw2.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc
http://tw2.php.net/manual/en/function.addslashes.php
http://tw2.php.net/manual/en/function.mysql-client-encoding.php
http://tw2.php.net/manual/en/function.mysql-escape-string.php

另一種解法是將錯就錯:
mysql-server 的編碼用預設的 latin1, 並且開啟 magic_quotes_gpc.
這樣子特殊中文字會加上 '\', 也剛好符合 latin1 編碼的資料庫的要求.

以前的解法:
http://chensh.loxa.edu.tw/php/X_1.php
http://blog.serv.idv.tw/archives/000017.php

不過, 千萬不要讓 mysql-server 和 mysql-client 的編碼不同, 這樣子問題會
更複雜 =.=...

如果小弟有錯請指正 ~>_<~.......