在处理文本数据时,通常需要支持不同的语言和字母表。为此,SQL使用排序规则——COLLATION。COLLATION定义了字符串的比较和排序方式。在列、表或查询级别正确设置COLLATION,以便正确处理语言特性(例如,ё ≠ е)。
SELECT * FROM users ORDER BY username COLLATE 'ru_RU.UTF8';
该查询按俄语字母顺序对用户进行排序。在不同的数据库管理系统中,collate的语法可能有所不同。
COLLATE utf8mb4_unicode_ci或utf8mb4_ru_0900_as_cs来考虑大小写和语言。COLLATE Cyrillic_General_CS_AS——支持俄语,区分大小写(CS = case sensitive,AS = accent sensitive)。重要提示: COLLATION也会影响搜索(LIKE、比较),不仅限于排序!
在一个查询中,对不同COLLATION的字符串进行排序时会遇到什么问题?是否可以在没有显式转换的情况下聚合不同排序规则的数据?
错误:如果COLLATION不同(例如,一个列是utf8mb4_unicode_ci,另一个是utf8mb4_bin),则在尝试进行UNION或直接比较时,会抛出COLLATION不兼容的错误。
正确做法:始终通过COLLATE语法将字符串转换为统一的COLLATION。
SELECT name COLLATE 'utf8mb4_unicode_ci' FROM customers UNION SELECT name COLLATE 'utf8mb4_unicode_ci' FROM suppliers;
故事1
在一个大型电子商务平台上,在将俄语客户列表导出为Excel时,发现以'Ё'开头的用户显示在列表的最后,'Е'开头的用户则在最前面。原因是COLLATION的不同——使用了标准的拉丁字母,而非俄语的,排序未能符合惯常的字母顺序。用户对不明显的排序表示不满。
故事2
在医疗系统中,不同表格包含具有不同COLLATION(默认为和明确指定的俄语)的字符串字段。更改表格方案后,汇总报告停止工作,查询开始返回"COLLATION conflict"。技术支持不得不在数百个查询中显式指定COLLATE。
故事3
用于按姓氏搜索的API只对大小写字母的精确拼写有效(区分大小写),尽管用户期望不区分大小写。结果发现,列是以COLLATION _CS创建的,这使得搜索对大小写敏感。更改为_CI(不区分大小写)后,问题得以解决。