MySQL查詢大小寫是否敏感問題分析


mysql數據庫在做查詢時候,有時候是英文字母大小寫敏感的,有時候又不是的,主要是由mysql的字符校驗規則的設置決定的,通常默認是不支持的大小寫字母敏感的。

 1. 什么是字符集和校驗規則?

字符集是一套符號和編碼。校對規則是在字符集內用於比較字符的一套規則。任何一個給定的字符集至少有一個校對規則,它可能有幾個校對規則。要想列出一個字符集的校對規則,使用SHOW COLLATION語句。

 

校對規則一般有這些特征:

  • 兩個不同的字符集不能有相同的校對規則。
  • 每個字符集有一個默認校對規則。例如,utf8默認校對規則是utf8_general_ci。
  • 存在校對規則命名約定:它們以其相關的字符集名開始,通常包括一個語言名,並且以_ci(大小寫不敏感)、_cs(大小寫敏感)或_bin(二元)結束。

2. 不同級別的字符集和校驗規則可控制大小寫敏感

MySQL5.1在同一台服務器、同一個數據庫或甚至在同一個表中使用不同字符集或校對規則來混合定義字符串。字符集和校對規則有4個級別的默認設置:服務器級、數據庫級、表級和連接級。

2.1服務器級

MySQL按照如下方法確定服務器字符集和服務器校對規則:

(1)修改配置文件/etc/my.cnf

在[mysqld]下添加:collation_server = utf8_bin

重啟實例

更改服務器級的校驗規則(collation_server )后,數據庫校驗規則(collation_collation)默認會繼承服務器級的。

注意:

    這個只適用於在重新啟動之后, 新建的庫,已存在的庫不受影響.

    同樣的, 即使庫的校驗規則改了,已經存在的表不受修改影響;

    同理與已經存在的列...

 謝謝丁奇的提醒

mysql> create database yutest0;
Query OK, 1 row affected (0.00 sec)
mysql> use yutest0;
Database changed
mysql> create table t1 (name varchar(10));
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t1 values('AAA');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1 values('aaa');
Query OK, 1 row affected (0.01 sec)

mysql> select * from t1;
+------+
| name |
+------+
| AAA  |
| aaa  |
+------+
2 rows in set (0.00 sec)

mysql> select * from t1 where name='aaa';
+------+
| name |
+------+
| aaa  |
+------+
1 row in set (0.00 sec)

可以看出,在服務器級進行相應的校對規則設置,查詢大小寫敏感。

(2)當服務器啟動時根據有效的選項設置

當啟動mysqld時,根據使用的初始選項設置來確定服務器字符集和校對規則。

shell> mysqld --character-set-server=latin1 --collation-server=latin1_swedish_ci

更改設定值的一個方法是通過重新編譯。如果希望在從源程序構建時更改默認服務器字符集和校對規則,使用:--with-charset和--with-collation作為configure的參量。例如:

shell> ./configure --with-charset=latin1 --with-collation=latin1_german1_ci

mysqld和configure都驗證字符集/校對規則組合是否有效。如果無效,每個程序都顯示一個錯誤信息,然后終止。

2.2數據庫級

MySQL這樣選擇數據庫字符集和數據庫校對規則:

  • 如果指定了character set X和collate Y,那么采用字符集X和校對規則Y。
  • 如果指定了character set X而沒有指定collate Y,那么采用character set X和character set X的默認校對規則。
  • 否則,采用服務器字符集和服務器校對規則。

(1)修改配置文件/etc/my.cnf

進行了兩組測試:

1) 在[mysqld]下添加:

collation_server = utf8_bin

collation_database = utf8_bin

2) 在[mysqld]下添加:

collation_database = utf8_bin

重啟實例,兩組都不能正常啟動,錯誤信息如下:

可見,my.cnf配置文件中不支持設置collation_database 變量。

(2)創建數據庫時設置數據庫校驗規則

mysql> create database yutest default character set utf8 collate utf8_bin;
Query OK, 1 row affected (0.00 sec)
mysql> show variables like 'collation_%';
+----------------------+-----------------+
| Variable_name        | Value           |
+----------------------+-----------------+
| collation_connection | utf8_general_ci |
| collation_database   | utf8_bin        |
| collation_server     | utf8_general_ci |
+----------------------+-----------------+
3 rows in set (0.00 sec)
mysql> select * from t1;
+------+
| name |
+------+
| ABC  |
| abc  |
+------+
2 rows in set (0.00 sec)

mysql> select * from t1 where name='abc';
+------+
| name |
+------+
| abc  |
+------+
1 row in set (0.01 sec)

可以看出,在數據庫級進行相應的校對規則設置,查詢大小寫敏感。

 2.3表級

MySQL按照下面的方式選擇表字符集和校對規則:

  • 如果指定了character set X和collate Y,那么采用character set X和collate Y。
  • 如果指定了character set X而沒有指定collate Y,那么采用character set X和character set X的默認校對規則。
  • 否則,采用數據庫字符集和服務器校對規則。

在創建表時設置表級校驗規則:

mysql> create database yutest2;
Query OK, 1 row affected (0.01 sec)
mysql> use yutest2;
Database changed

mysql> create table t1(name varchar(10))
    -> default character set utf8 collate utf8_bin;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t1 values('ABC');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1 values('abc');
Query OK, 1 row affected (0.00 sec)

mysql> show variables like 'collation_%';
+----------------------+-----------------+
| Variable_name        | Value           |
+----------------------+-----------------+
| collation_connection | utf8_general_ci |
| collation_database   | utf8_general_ci |
| collation_server     | utf8_general_ci |
+----------------------+-----------------+
3 rows in set (0.00 sec)

mysql> select * from t1;
+------+
| name |
+------+
| ABC  |
| abc  |
+------+
2 rows in set (0.00 sec)

mysql> select * from t1 where name='abc';
+------+
| name |
+------+
| abc  |
+------+
1 row in set (0.00 sec)

可以看出,在表級進行相應的校對規則設置,查詢大小寫敏感。

 2.4 連接級

考慮什么是一個“連接”:它是連接服務器時所作的事情。客戶端發送SQL語句,例如查詢,通過連接發送到服務器。服務器通過連接發送響應給客戶端,例如結果集。對於客戶端連接,這樣會導致一些關於連接的字符集和校對規則的問題,這些問題均能夠通過系統變量來解決:

mysql> show variables like 'character%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)
  • 當查詢離開客戶端后,在查詢中使用哪種字符集?

服務器使用character_set_client變量作為客戶端發送的查詢中使用的字符集。

  • 服務器接收到查詢后應該轉換為哪種字符集?

轉換時,服務器使用character_set_connection和collation_connection系統變量。它將客戶端發送的查詢從character_set_client系統變量轉換到character_set_connection。

  • 服務器發送結果集或返回錯誤信息到客戶端之前應該轉換為哪種字符集?

character_set_results變量指示服務器返回查詢結果到客戶端使用的字符集。包括結果數據,例如列值和結果元數據(如列名)。

3. 創建數據庫表時大小寫不敏感,仍然有方法在查詢時區分大小寫

3.1 SQL語句中使用collate

使用collate子句,能夠為一個比較覆蓋任何默認校對規則。collate可以用於多種SQL語句中,比如where,having,group by,order by,as,聚合函數。

mysql> select * from t1 where name collate utf8_bin = 'ABC';
+------+
| name |
+------+
| ABC |
+------+
1 row in set (0.00 sec)

mysql> select * from t1 where name = 'ABC';
+------+
| name |
+------+
| ABC |
| Abc |
| abc |
+------+
3 rows in set (0.00 sec)

mysql> select * from t1;
+------+
| name |
+------+
| ABC |
| Abc |
| abc |
+------+
3 rows in set (0.00 sec)

3.2 binary操作符

binary操作符是collate子句的一個速記符。binary 'x'等價與'x' collate y,這里y是字符集'x'二元校對規則的名字。每一個字符集有一個二元校對規則。例如,latin1字符集的二元校對規則是latin1_bin,因此,如果列a是字符集latin1,以下兩個語句有相同效果:

select * from t1 order by binary a;

select * from t1 order by a collate latin1_bin;

 

mysql> select * from t1 where binary name = 'ABC';
+------+
| name |
+------+
| ABC |
+------+
1 row in set (0.00 sec)
mysql>
mysql> select * from t1 where name = 'ABC';
+------+
| name |
+------+
| ABC |
| Abc |
| abc |
+------+
3 rows in set (0.00 sec)

 

參考鏈接:

MySQL5.1參考手冊 http://dev.mysql.com/doc/refman/5.1/en/charset-server.html

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM