我在MYSQL表中有一些列,它们将包含不同语言的唯一字符串,并且在某些情况下某些字符会匹配,例如带有瑞典语A和MYSQL的英语A会将它们视为平等。
所以我正在考虑对这些列使用UTF8_bin
排序规则,因为它似乎更合适。
问题是,对于UTF_8_bin
,唯一索引不会区分大小写,因此如果两个字符串都是相同的语言,则可以使用'Andreas'和'andreas'。
有没有解决方法呢?
答案 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('ä');
这意味着您的查询将使用不同的列进行比较和更新(如果您使用框架,可能需要进一步调整),但如果它们是完美的,则不会将变通方法称为变通方法。