为何MariaDB 10.2中RLIKE会匹配4字节表情符号?
问题解析:MariaDB 10.2正则
^[?]+$匹配4字节表情符号的原因及解决办法 问题现象
执行以下SQL时,本应仅匹配问号字符的正则表达式^[?]+$,却匹配了4字节表情符号😃,返回结果为1(匹配成功):
(root@127.0.0.1:3306) [test]> select '😃' RLIKE '^[?]+$'; +-----------------------------------+ | '\xF0\x9F\x98\x83' RLIKE '^[?]+$' | +-----------------------------------+ | 1 | +-----------------------------------+ 1 row in set (0,00 sec)
当前数据库排序规则均为utf8mb4_general_ci:
(root@127.0.0.1:3306) [test]> SHOW VARIABLES LIKE 'collation%'; +----------------------+--------------------+ | Variable_name | Value | +----------------------+--------------------+ | collation_connection | utf8mb4_general_ci | | collation_database | utf8mb4_general_ci | | collation_server | utf8mb4_general_ci | +----------------------+--------------------+ 3 rows in set (0,00 sec)
原因
MariaDB中RLIKE/REGEXP的匹配行为会受当前字符集排序规则的影响:
utf8mb4_general_ci是通用排序规则,它的字符等价映射逻辑比较宽松,会将部分Unicode字符(包括你测试的这个4字节表情符号)与问号?视为“等价字符”,导致正则字符类[?]会匹配到这些被归为等价的字符。- 这种等价匹配是排序规则的设计特性,目的是简化某些场景下的字符比较,但在正则精确匹配时会带来意外结果。
解决办法
1. 使用二进制匹配(临时方案)
在正则表达式前添加BINARY修饰符,强制按字符的原始字节值进行精确匹配,忽略排序规则的等价映射:
select '😃' RLIKE BINARY '^[?]+$';
执行后会返回0,即不匹配表情符号,仅匹配问号。
2. 更换更严格的排序规则(长期方案)
将数据库/表/列的排序规则更换为utf8mb4_unicode_ci或更现代的规则(如MariaDB 10.3+支持的utf8mb4_unicode_520_ci),这类排序规则的字符等价映射更符合Unicode标准,不会将表情符号与问号归为一类。
修改数据库排序规则的示例:
ALTER DATABASE test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
注意:修改排序规则可能影响已有数据的查询结果,建议先做测试再批量修改。
3. 改用REGEXP_LIKE函数(若版本支持)
MariaDB 10.0.5及以上支持REGEXP_LIKE函数,可通过指定c(大小写敏感,且按字符精确匹配)修饰符实现精确匹配:
SELECT REGEXP_LIKE('😃', '^[?]+$', 'c');
该语句同样会返回0,实现预期的精确匹配效果。
内容的提问来源于stack exchange,提问作者Ela
相关产品推荐
相关产品推荐

