ascii()函数仅返回字符串首字符的ascii码值,如ascii('ab')得97;处理多字符需配合substring()逐位提取,且不适用于utf-8多字节字符解析。

MySQL里ASCII()函数只能取第一个字符的码值
很多人以为ASCII()能处理整个字符串,结果发现ASCII('ab')返回的是97(‘a’的ASCII码),不是“97,98”。它只认第一个字符,后面全忽略。这点和ORD()行为一致,但和PostgreSQL的ascii()或Python的ord()用法容易混淆。
实操建议:
- 如果要批量查多个字符的ASCII码,得配合
SUBSTRING()逐位提取:SELECT ASCII(SUBSTRING('hello', 1, 1)), ASCII(SUBSTRING('hello', 2, 1)) - 想一次性展开整串,用
JSON_ARRAY()+ 循环逻辑太重,不推荐;真有这需求,优先考虑应用层处理 -
ASCII(NULL)返回NULL,不是0或报错,注意空值传播
用CHAR()反向转换时要注意字符集和长度限制
CHAR(65, 66, 67)确实能返回'ABC',但它依赖当前连接的字符集。如果客户端是utf8mb4,而传入的码值超过0–255(比如CHAR(500)),MySQL会截断或静默转成问号,不报错也不警告。
实操建议:
- 只在0–255范围内使用
CHAR()最安全,对应标准ASCII可打印字符 - 传入负数或大于255的值,不同MySQL版本行为不一:5.7可能转成0,8.0可能报
Warning 1265 Data truncated - 拼接多字节字符(如中文)别指望
CHAR()——它不支持UTF-8码点,CHAR(228)不是“你”,而是ä(Latin-1里的字符)
WHERE条件里用ASCII()做前缀筛选效率很低
比如写WHERE ASCII(name) = 77查首字母为'M'的记录,看着简洁,但会导致name字段无法走索引——因为函数作用于列上,优化器没法用B+树快速定位。
实操建议:
- 想按首字母查,直接用
WHERE name LIKE 'M%',能命中索引 - 真要基于ASCII码做范围判断(比如排除控制字符),先确认该字段基数低、查询频次少,否则加生成列索引更稳妥:
ALTER TABLE t ADD COLUMN first_ascii TINYINT AS (ASCII(name)) STORED - 注意:
ASCII('')返回0,空字符串和NULL要分开判断,WHERE ASCII(col) > 0会漏掉NULL和空串
和HEX()、UNHEX()混用时容易搞错编码层级
ASCII('A')是65,HEX('A')是'41',看起来只是进制差异,但一旦涉及多字节字符就彻底不是一回事。比如HEX('你')返回'E4F6A0'(UTF-8三字节),而ASCII('你')只取首字节E4对应的十进制228,完全丢失原意。
实操建议:
- 别用
ASCII()去解析UTF-8字符串,它没能力识别多字节边界 - 需要二进制级操作(如协议头校验),优先用
ORD()(MySQL 8.0+)或直接存VARBINARY字段 -
UNHEX(HEX(col))能还原原始值,但CHAR(ASCII(col))对中文永远只还第一个字节对应的乱码字符
ASCII函数本身很简单,但它的“简单”恰恰是最容易让人掉以轻心的地方——它只管字节,不管语义,也不管上下文字符集。用之前,先想清楚你真正想比对的是字节值,还是字符含义。











