mysql校对规则_MYSQL校对规则
一、前言
有時候遇到這種情況,你用一個like語句查詢,查到的結(jié)果中有一些并沒有包含你查詢的關(guān)鍵詞的紀(jì)錄;
有時候遇到這種情況,你的數(shù)據(jù)庫自作聰明的大小寫不敏感,讓你在更新時把大小寫不同的兩條記錄都更新了;
有時候遇到這種情況,你的查詢語句一切正常,查詢卻失敗了,報(bào)告Illegal mix of collations錯誤;
你很困惑,在想數(shù)據(jù)庫是不是壞了。。。其實(shí) ,這些都和數(shù)據(jù)庫字符集的校對規(guī)則有關(guān);了解了校對規(guī)則,你就知道怎樣處理這些問題。
那么,校對規(guī)則是怎么回事呢?它是一組規(guī)則,負(fù)責(zé)決定某一字符集下的字符進(jìn)行比較和排序的結(jié)果。
比如說,有l(wèi)atin1字符集中的字母A和a,我們需要它們在比較的時候相等,那么,我們可以使用字符集校對規(guī)則 latin1_general_ci;這種校對規(guī)則在比較和排序的時候不區(qū)分大小寫;如果我們需要他們在比較的時候不等呢?也很簡單,我們可以使用字符集校對規(guī)則latin1_bin;這種校對規(guī)則會以二進(jìn)制的方式對字符進(jìn)行比較,很明顯,a和A的二進(jìn)制編碼不同,比較的結(jié)果就是不等。
上面的場景說明了校對規(guī)則在最簡單情況下起的作用;實(shí)際情況與此并沒有太多不同,只不過稍微有些復(fù)雜而已。
二、校對規(guī)則總覽
我們可以使用SHOW COLLATION 指令來查看數(shù)據(jù)庫支持的校對規(guī)則
在圖中,我們列出了數(shù)據(jù)庫支持的latin1字符集的校對規(guī)則。為什么一種字符集竟然有這么多種的校對規(guī)則呢?因?yàn)樵诓煌那闆r下,對比較的結(jié)果有不同的期待,所以就有了不同的校對規(guī)則。前面說的大小寫敏感(latin1_general_cs)和不敏感(latin1_general_ci)是兩種校對規(guī)則,根據(jù)二進(jìn)制方式進(jìn)行比較(latin1_bin)也是一種校對規(guī)則,德國人(latin1_german1_ci)和西班牙人(latin1_spanish_ci)使用的某些不同的拉丁字符在某些情況下是等價(jià)的,所以有了兩種新的校對規(guī)則。
舉個例子,在latin1_german1_ci中,如下字符是等價(jià)的,而他們,具有不同的外形和編碼。當(dāng)然,它們的編碼不同,所以在latin1_bin校對規(guī)則下,他們又是不等價(jià)的了。
A,a,à,á,?,?,?,?,?,à,á,a,?,?,?,?
三、校對規(guī)則導(dǎo)致的問題
1、混合校對規(guī)則比較
兩個字符串比較,要求兩者必須有相同的校對規(guī)則,或者兩者的校對規(guī)則是相容的——所謂相容是指,兩種校對規(guī)則優(yōu)先級不同,比較的時候兩者使用高優(yōu)先級的校對規(guī)則進(jìn)行比較,比如latin1_bin的優(yōu)先級相對較高。
CREATE TABLE `tbl` (
`col_a` int(11) default NULL,
`col_b` char(20) character set latin1 collate latin1_general_ci default NULL,
`col_c` char(20) character set latin1 collate latin1_german1_ci default NULL,
`col_d` char(20) character set latin1 collate latin1_bin default NULL,
KEY `col_a` (`col_a`),
KEY `col_b` (`col_b`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
在這個表中,col_b、col_c、col_d的校對規(guī)則各不同;其中,latin1_general_ci和latin1_german1_ci 校對規(guī)則同級,不能進(jìn)行比較;如果強(qiáng)行比較的話,就會報(bào)錯,如下:
mysql> select * from tbl where col_b = col_c;
ERROR 1267 (HY000): Illegal mix of collations (latin1_general_ci,IMPLICIT) and (latin1_german1_ci,IMPLICIT) for operation '='
而latin1_general_ci和latin1_bin的優(yōu)先級不同,latin1_bin高于latin1_general,因此比較的時候,會按照latin1_bin的規(guī)則進(jìn)行比較。
mysql> select * from tbl where binary col_b = col_d;
Empty set (0.00 sec)
當(dāng)然,可以在sql語句中強(qiáng)制指定校對規(guī)則進(jìn)行比較,下面這個例子就說明了這一點(diǎn):
mysql> select * from tbl where col_b COLLATE latin1_danish_ci = col_c COLLATE latin1_danish_ci;
Empty set (0.00 sec)
2、校對規(guī)則導(dǎo)致的問題——SELECT出錯誤的記錄
在上面的基礎(chǔ)上,我們要演示一個常見的問題;我們需要對該數(shù)據(jù)表進(jìn)行一定的處理:
alter table tbl modify col_b collate latin1_swedish_ci default null;
insert into tbl (col_b) values ('hao123');
然后進(jìn)行下面的查詢
我們希望查詢的是包含“劉”的記錄,hao123這個和“劉”沒有任何關(guān)系的條目被選了出來,看起來很奇怪。
不過這不是數(shù)據(jù)庫出了問題,而是校對規(guī)則的使用上存在問題:
下面是我們使用ultraedit察看字符串的二進(jìn)制編碼的結(jié)果,在gbk編碼下,hao123的編碼為68 61 6f 31 32 33,而劉的編碼位C1 F5。
在前面的latin1_swedish_ci 校對規(guī)則中可以看到:
61和C1都與41等價(jià)
6F和F5都與4F等價(jià)
這就是ao = 劉的原因。
解決辦法有兩個:
1)修改該字段的字符集和校對規(guī)則,改成gbk,這該問題不在存在。這是完美的解決方案,不過有些時候你沒有權(quán)限對數(shù)據(jù)庫進(jìn)行這樣的改動。
mysql> alter table tbl modify col_b char(20) charset gbk default null;
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from tbl where binary col_b like like '%劉%';
Empty set (0.00 sec)
2)查詢的時候聲明校對規(guī)則為latin1_bin 。這樣可以在一定程度上緩解這個問題;不過如果col_b中只要含有c1 f5,就會被選出來——而c1 f5可能恰好是另外兩個字符的前半截和后半截,或者干脆就是 á ? ....
mysql> select * from tbl where binary col_b like '%劉%';
Empty set (0.00 sec)
轉(zhuǎn)載:http://hi.baidu.com/cuttinger/item/e23013e372ee62adce2d4fda
總結(jié)
以上是生活随笔為你收集整理的mysql校对规则_MYSQL校对规则的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql 更新索引_MySQL索引优化
- 下一篇: 静待发布!魅族20系列无界超前订已突破3