HEX() 将字符串按字节编码(如utf8mb4)转为大写十六进制字符串,非按字符;数字转十六进制不补零;NULL返回NULL;还原须用严格校验的UNHEX()。

HEX() 函数怎么把字符串转成十六进制
直接用 HEX() 就行,它默认把输入的字符串按字节逐个转成两位十六进制大写表示。比如中文、emoji、二进制 blob 都能转,但要注意底层是按字节编码处理的,不是按字符。
常见错误现象:HEX('你好') 返回的是 UTF-8 编码字节序列(如 E4BDA0E5A5BD),不是 GBK 或 Unicode 码点;有人误以为是“字符的十六进制值”,结果比对失败。
- 输入是字符串:按当前连接字符集(通常是
utf8mb4)编码后转字节 - 输入是数字:
HEX(255)→FF,等价于整数转十六进制字符串,不补零 - 输入是 NULL:返回 NULL,不是空字符串
- 想转回原内容?得用
UNHEX(),且必须保证原始字节完整(不能被截断或中间加空格)
UNHEX() 还原时为什么总得到 NULL 或乱码
UNHEX() 对输入极其严格:只接受长度为偶数的纯十六进制字符串(0-9、A-F、a-f),任何非法字符、奇数长度、空格都会让整个函数返回 NULL —— 不报错,也不警告,容易误判为“数据丢了”。
使用场景:常用于还原从日志、API 或前端传来的 hex 字符串(比如加密后的 token、图片 blob 的 hex 表示)。
- 检查长度:
LENGTH(col_hex) % 2 != 0→ 必然失败 - 过滤干扰字符:前端传来的
"0xABC"或"ab cd ef"都要先用REPLACE()和正则(MySQL 8.0+)清洗 - 兼容性注意:MySQL 5.7 不支持正则替换,得靠嵌套
REPLACE(REPLACE(...))去空格和前缀 - 性能影响:
UNHEX()是逐字节解析,大数据量时别在 WHERE 条件里对字段反复调用,尽量提前解码存到新列
HEX() 和 CONV() 在进制转换上的根本区别
HEX() 是编码/序列化函数,CONV() 是纯数学进制转换函数,二者目的不同,不能混用。
典型误用:CONV(HEX('a'), 16, 10) 想“把字符 a 转成十进制”,结果是 273(即 0x61 = 97,但你算的是 0x61 当作十六进制数转十进制 → 6×16 + 1 = 97?不对,HEX('a') 是字符串 '61',CONV('61', 16, 10) = 97,看似对,但逻辑链断裂——你其实绕了远路。
-
HEX():面向字节流,输出字符串,用于存储、传输、调试 -
CONV(str, from_base, to_base):面向数值,str必须是合法进制下的数字字符串(如'1010'、'FF'),不关心编码 -
CONV()不支持小数点,不支持负号,超出范围返回 NULL - 性能上:
HEX()更快,CONV()涉及多步数学运算,大数据量聚合时差异明显
实际项目中 HEX() 最容易踩的三个坑
不是语法不会用,而是业务上下文没对齐。最常发生在日志分析、密码迁移、二进制字段导出这几个场景。
- 导出 BLOB 字段时只用
SELECT HEX(blob_col)→ 结果可能被客户端截断(默认max_allowed_packet限制),需提前设大或分块取 - 比对加密哈希值(如 SHA256)时,数据库存的是
HEX()结果,但代码里用了base64或小写 hex,导致永远不等 —— 注意大小写敏感和编码一致性 - 在 WHERE 中写
WHERE HEX(name) = 'E4BDA0'→ 无法走索引,全表扫描。正确做法是建生成列 + 索引:ALTER TABLE t ADD COLUMN name_hex VARCHAR(200) STORED AS (HEX(name))
HEX() 看似简单,但一旦涉及跨系统、跨语言、跨字符集,字节层面的细节就会浮上来——漏掉一个编码假设,后面所有比对和还原都不可靠。


















