讓MySQL支援歐元字元

2021-09-23 22:50:14 字數 2679 閱讀 4517

本文說明一下mysql中不支援歐元字元的原因及解決方法。

1、

問題描述

在mysql中插入的字串中若包含歐元字元(€)

,會發現該字元及以後的字串都變得「不可見」。實際上這裡並非不可見,而是根本沒有進入資料庫中。簡單描述步驟如下:

root@test 05:15:41>create table t(c char(32)) engine=innodb charset=gbk;

query ok, 0 rows affected (0.01 sec)

root@test 05:16:29>insert into t values(concat('a', char(128), 'b'));

query ok, 1 row affected, 1 warning (0.00 sec)

root@test 05:17:04>select * from t;

+------+

| c    |

+------+

| a    |

+------+

可以看到,我們試圖插入三個字元(a, €, b)

,但在查詢中發現只有乙個字元a.

insert的乙個warning內容為incorrect string value: '\x80b' for column 'c' at row 1

說明在插入0x80(即€) 時出錯,導致後面的字元也一起被丟棄.

2、

原因分析

我們知道,在mysql

將語句中設定的值傳給引擎時,需要先拷貝到乙個臨時結構中。但拷貝字串只會以\0

結束,0x80

對於字串拷貝過程應該是乙個正常的字元。

拷貝函式

於是我們找到做值拷貝的過程,

在sql/sql_string.cc

的well_formed_copy_nchars

中,對應的兩行**如下

res= to_cs->cset->well_formed_len(to_cs, from, from + from_length, 

nchars, &well_formed_error);

memmove(to, from, res);

可以看到,拷貝內容時,先計算了可拷貝的長度,然後在用memmove. 除錯

發現,在我們上面的試驗中,返回的res=1

,因此memmove

就只拷貝了乙個字元(a).

計算長度

於是問題出在這個to_cs->cset->well_formed_len

中。由於mysql

要支援多種字元編碼,因此定義了my_charset_handler (

在include/m_ctype.h)

中,這個結構體定義了各種編碼下的特定函式介面。對應的實現實體在strings/ctyp-*.c

中。我們的例子中用到的是gbk

,因此看strings/ctype-gbk.c

。上述計算長度的函式,實際上呼叫的是本檔案中的my_well_formed_len_gbk

static

size_t my_well_formed_len_gbk(charset_info *cs __attribute__((unused)),

const char *b, const char *e,

size_t pos, int *error)

else if ((b < emb) && isgbkcode((uchar)*b, (uchar)b[1]))

else

} return (size_t) (b - b0);

}

第12行是對於英文本元的處理,第17行是對於中文字元的處理,其他的直接到第22行後判為error

。我們看到,0x80

就到了*error=1, 

然後break

3、

修改和小結

實際上歐元字元也可以作為單位元組處理, 將上面**的第12行改為if ((uchar) b[0] <= 128)

,重新編譯後執行結果如下

mysql> insert into t values(concat('a', char(128), 'b'));

query ok, 1 row affected (0.00 sec)

insert select hex(c) from t;

+--------+

| hex(c) |

+--------+

| 618062 |

+--------+

歐元字元在筆者客戶端內顯示不正常,但從hex(c)

中看到三個字元已經正常儲存在mysql

中。其他字元編碼也有此問題,都修改相應的string/ctype-*.c

中的my_well_formed_len*

即可。

mysql 元字元 菜鳥教程元字元總結

字元描述 將下乙個字元標記為乙個特殊字元 或乙個原義字元 或乙個 向後引用 或乙個八進位制轉義符。例如,n 匹配字元 n n 匹配乙個換行符。序列 匹配 而 則匹配 匹配輸入字串的開始位置。如果設定了 regexp 物件的 multiline 屬性,也匹配 n 或 r 之後的位置。匹配輸入字串的結束...

讓mysql支援中文

我用spring ibatis mysql搭了乙個框架,但是中文顯示亂碼。解決問題的路徑 1 在資料庫連線的url 後加上 useunicode true characterencoding utf8 2 修改mysql的配置檔案my.ini 在 client 後加上default characte...

mysql 元字元 正規表示式 元字元的使用

一 基本簡介 1.定義 即文字的高階匹配模式,提供搜尋,替換等功能。其本質是由一系列字元和特殊符號構成的字串,這個字串即正規表示式。2.原理 通過普通字元和有特定含義的字元,來組成字串,用以描述一定的字串規則,比如 重複,位置等,來表達某類特定的字串,進而匹配。3.目標 熟練掌握正規表示式元字元 能...