MYSQL UTF8_bin不区分大小写的唯一索引

时间:2016-09-25 09:44:21

标签: mysql

我在MYSQL表中有一些列,它们将包含不同语言的唯一字符串,并且在某些情况下某些字符会匹配,例如带有瑞典语A和MYSQL的英语A会将它们视为平等。

所以我正在考虑对这些列使用UTF8_bin排序规则,因为它似乎更合适。

问题是,对于UTF_8_bin,唯一索引不会区分大小写,因此如果两个字符串都是相同的语言,则可以使用'Andreas'和'andreas'。

有没有解决方法呢?

1 个答案:

答案 0 :(得分:1)

您可以使用生成的列来存储字符串的小写版本,并使用唯一索引。

create table test_utf8_bin_ci
( u8 varchar(50) charset utf8mb4 collate utf8mb4_unicode_ci,
  u8_bin_ci varchar(50) charset utf8mb4 collate utf8mb4_bin as (lower(u8)) unique
);

insert into test_utf8_bin_ci (u8)
values ('A'),('Ä'),('Å'),('Â'),('Á'),('À');

insert into test_utf8_bin_ci (u8)
values ('å');

Error Code: 1062. Duplicate entry 'å' for key 'u8_bin_ci'

对于5.7.8之前的MySQL版本,尚不支持生成列的索引。因此,您需要添加“普通”列(不包含as (lower(u8)))并计算insert / update触发器中的值。唯一索引的工作方式与计算列的工作方式相同,只需要编写代码即可。

create trigger trbins_test_u8_bin_ci before insert on test_u8_bin_ci
for each row 
  set new.u8_bin_ci = lower(new.u8);
create trigger trbupd_test_u8_bin_ci before update on test_u8_bin_ci
for each row 
  set new.u8_bin_ci = lower(new.u8);

如果你使用_bin,你应该知道很多函数不再是不区分大小写的,例如。

select * 
from test_utf8_bin_ci 
where u8 = 'ä';

不会给你任何结果。为了能够使用索引进行搜索(如果您使用例如where lower(u8) = lower('ä'),这是不可能的),您可以使用

select * 
from test_utf8_bin_ci 
where u8_bin_ci = lower('ä');

这意味着您的查询将使用不同的列进行比较和更新(如果您使用框架,可能需要进一步调整),但如果它们是完美的,则不会将变通方法称为变通方法。