MySQL查詢關於區分字母大小寫問題
前段時間在工作中測試提出了一個BUG,讓我把根據ID查詢區分大小寫的功能去掉,大小寫都隨便查,然後我在SQL的位置加上了UPPER(id) = UPPER(#{id})
的寫法,而同事知道這個問題後的反映是"MySQL查詢不是本就不區分大小寫嗎",後來我找機會簡單瞭解了一下才明白,MySQL區分大小寫取決於資料庫的排序規則,今天在這裡記錄一下
一般建立資料庫都會使用utf8
編碼,對應兩種常用的排序規則就是utf8_bin
和utf8_general_ci
,其中utf8_bin
就是區分大小的排序規則,另一個就是不區分大小寫的排序規則,接下來針對排序規則進行一些簡單的測試
注意:本人使用的Navicat客戶端工具,其他客戶端工具可能會對測試結果造成影響(例如SQLyog)
先測試區分大小寫的排序規則
-- 建立區分大小寫的資料庫 CREATE DATABASE test DEFAULT CHARACTER SET utf8 COLLATE utf8_bin; -- 選擇資料庫 USE test; -- 建立一張測試表 CREATE TABLE aaa ( id VARCHAR(16), PRIMARY KEY(id) ); -- 插入測試資料 INSERT INTO aaa VALUES('abc'); -- 正常查詢,可以查詢到結果 SELECT id FROM aaa WHERE id = 'abc'; -- 修改大小寫後,查詢不到結果 SELECT id FROM aaa WHERE id = 'abC';
可以看出排序規則為bin
的資料庫使用查詢是區分大小寫的,然後再測試一下不區分大小寫的
-- 建立不區分大小寫的資料庫 CREATE DATABASE test2 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; -- 選擇資料庫 USE test2; -- 建立一張測試表 CREATE TABLE aaa ( id VARCHAR(16), PRIMARY KEY(id) ); -- 插入測試資料 INSERT INTO aaa VALUES('abc'); -- 正常查詢,可以查詢到結果 SELECT id FROM aaa WHERE id = 'abc'; -- 修改大小寫後同樣可以查詢到結果 SELECT id FROM aaa WHERE id = 'abC';
可以看出general_ci
是不區分大小寫的,有了結論後我們把test
庫修改為不區分大小寫試試看
-- 將資料庫的排序規則修改為utf8_general_ci
ALTER DATABASE test CHARACTER SET utf8 COLLATE utf8_general_ci;
-- 選擇test資料庫
USE test;
-- 再次查詢,還是查詢不到結果
SELECT id FROM aaa WHERE id = 'abC';
這裡已經把資料庫的排序規則修改了,怎麼還是查不到資料呢?原因是因為直接改庫只對以後建立的表生效,並不會對已存在的表造成影響,這裡新建一張表來測試一下
CREATE TABLE bbb (
id VARCHAR(16),
PRIMARY KEY(id)
);
INSERT INTO bbb VALUES('bbb');
SELECT id FROM bbb WHERE id = 'bBb';
果然,後續建立的表是不區分大小寫的,接下來需要讓已經建立的表也不區分大小寫,這裡直接修改表的排序規則試試
-- 將表的排序規則修改為utf8_general_ci
ALTER TABLE aaa DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
-- 再次查詢,還是查詢不到結果
SELECT id FROM aaa WHERE id = 'abC';
修改表的排序規則不行,那就修改欄位(列)的排序規則
-- 將欄位的排序規則修改為utf8_general_ci
ALTER TABLE aaa MODIFY id VARCHAR(16) CHARACTER SET utf8 COLLATE utf8_general_ci;
-- 再次查詢,查詢成功!
SELECT id FROM aaa WHERE id = 'abC';
通過測試我們可以知道,排序規則分別有三個生效的作用域,分別是 列、表、庫,而他們之間生效的優先順序為列 > 表 > 庫
,只要列的排序規則修改成功,表和庫的排序規則對於列來說就不重要了
經過測試瞭解到如果想要某個欄位不區分大小寫查詢,就執行如下SQL修改他的排序規則即可:
ALTER TABLE [表名] MODIFY [欄位名] [欄位型別] CHARACTER SET utf8 COLLATE utf8_general_ci;
如果表中有大批欄位需要修改的話一個一個改很麻煩,可以呼叫這段SQL修改表以及表中所有欄位
ALTER TABLE [表名] CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
擴充套件
其實除了utf8_general_ci
排序規則之外,utf8_unicode_ci
同樣不區分大小寫,只不過unicode
相對於general
效率較低,但是查詢精準度更高一些,詳情點選這裡(其實我也不懂)
作者多數為原創文章 ( 部分轉載已標出 ),目前資歷尚淺文章內描述可能有誤,對此造成的後果深表歉意,如有錯誤還望指正