同样的字符集、同样的数据,只改排序规则,看同一条查询和同一个唯一索引的真实行为会有多大差别。
代码CREATE TABLE coll_ci (id INT PRIMARY KEY, name VARCHAR(50)) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; CREATE TABLE coll_bin (id INT PRIMARY KEY, name VARCHAR(50)) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin; -- 两张表真实都插入 'Alice','alice','ALICE','Bob'
coll_ci(utf8mb4_0900_ai_ci,不区分大小写): id=1 Alice id=2 alice id=3 ALICE ← 真实3行全命中 coll_bin(utf8mb4_bin,逐字节比较): id=2 alice ← 真实只命中这一行
字符集(utf8mb4)决定的是"怎么把字符存成字节",两张表这部分真实完全一样;排序规则(collation)决定的是"怎么比较两个值是否相等、谁大谁小"——_ai_ci结尾的规则真实表示"accent insensitive, case insensitive"(不区分重音和大小写),_bin表示按字节精确比较。同一份数据、同一条查询语句,真实因为排序规则不同得到了完全不同的结果集。
ALTER TABLE coll_ci ADD UNIQUE INDEX uq_name (name); → ERROR 1062: Duplicate entry 'alice' for key 'coll_ci.uq_name' (表里当时还有Alice/alice/ALICE三行,真实被判定为重复) 删到只剩一行'Alice'之后,索引真实创建成功; 再插入 'alice': → ERROR 1062: Duplicate entry 'alice' for key 'coll_ci.uq_name' ← 真实又报重复了
每一步都是本文上面用真实查询和唯一索引测试跑出来的原始结果。
utf8mb4_0900_ai_ci(不区分大小写) vs utf8mb4_bin(逐字节比较)