MySQL迁移Redshift时如何忽略排序规则实现Á与a匹配效果一致
问题根因
匹配结果不一致的核心原因是两款数据库的字符比较逻辑存在差异:
- 你当前MySQL环境使用的非utf8mb4的
utf8字符集,默认搭配utf8_general_ci排序规则,该规则同时不区分大小写、不区分字母重音,基础字母和带变音符号的同根字母(比如示例里的a和Á)会被判定为相等。 - Redshift内置的
case_insensitive排序规则仅实现了大小写不敏感,默认仍会区分重音符号,因此会将a和Á判定为不同字符。你之前尝试的collate写法只覆盖了大小写忽略逻辑,没有处理重音忽略的需求,自然无法得到预期结果。
可落地解决方案
根据是否能修改表结构,可选择以下两种方案实现和MySQL一致的比较行为:
方案1:使用大小写+重音双不敏感排序规则
Redshift原生提供了同时忽略大小写和重音的排序规则case_insensitive_accent_insensitive,直接在关联条件中给两个字段应用该规则即可,修改后的SQL如下:
SELECT * FROM a JOIN b ON a.name COLLATE case_insensitive_accent_insensitive = b.name COLLATE case_insensitive_accent_insensitive;
如果这类比较是业务常态,可以在建表阶段直接给对应name字段指定该排序规则,后续所有关联、过滤操作都会默认遵循该比较逻辑,无需每次查询手动加collate声明。
方案2:字段值标准化后比较
如果没有修改表结构的权限,也可以在比较前对字段值做统一标准化处理:先移除字符上的重音符号,再统一转小写后做等值判断,示例写法:
SELECT * FROM a JOIN b ON LOWER( TRANSLATE( a.name, 'ÁÀÂÄÃÅáàâäãåÉÈÊËéèêëÍÌÎÏíìîïÓÒÔÖÕóòôöõÚÙÛÜúùûüÑñÇç', 'AAAAAAaaaaaaEEEEeeeeIIIIiiiiOOOOOoooooUUUUuuuuNnCc' ) ) = LOWER( TRANSLATE( b.name, 'ÁÀÂÄÃÅáàâäãåÉÈÊËéèêëÍÌÎÏíìîïÓÒÔÖÕóòôöõÚÙÛÜúùûüÑñÇç', 'AAAAAAaaaaaaEEEEeeeeIIIIiiiiOOOOOoooooUUUUuuuuNnCc' ) );
该写法不依赖表结构配置,兼容性更强,适合临时查询场景。
注意:上述方案匹配的是MySQL
utf8_general_ci的默认比较行为,如果你的MySQL实例自定义了其他排序规则,需要对应调整Redshift侧的比较逻辑。
内容的提问来源于stack exchange,提问作者Nir
相关产品推荐
相关产品推荐

