hex和unhex是mysql中唯一能安全转义二进制数据的sql内置方案,用于避免引号、nul字节等被解析层误判;hex将blob/varbinary转为纯ascii十六进制字符串,unhex则可安全还原为binary类型,支持预处理变量,但输入须偶数长度且仅含0-9a-f字符,否则静默返回null。

HEX 和 UNHEX 不是“更高效”的通用函数,而是唯一能安全绕过 SQL 解析层污染的二进制数据转义方案。 它们的价值不在 CPU 时间或执行速度,而在于避免引号、反斜杠、NUL 字节等被客户端/驱动/SQL 解析器误判或截断 —— 尤其在导出导入 BLOB、VARBINARY 或 UUID 字段时,这是刚需,不是优化项。
HEX() 是唯一能无损把二进制转成纯 ASCII 字符串的函数
MySQL 的字符串字面量(比如 'abc')和 SQL 语句本身都运行在文本协议层。一旦字段含 \0、'、\n、\r 或高位字节(如 UTF-8 中的多字节字符首字节),直接拼 SQL 就会出错或静默损坏。
-
HEX(bin_field)输出全是 0–9、A–F 的 ASCII 字符,不依赖字符集,不触发任何转义逻辑 - 输出长度恒为原数据长度 × 2,可预测、可校验(比如用
LENGTH(HEX(bin_field)) % 2 = 0快速筛异常) - 注意:
HEX()对数字参数行为不同(如HEX(255)→'FF'),但对BLOB或VARBINARY字段,传入的是二进制值,走的是字符串路径,每个字节转两位十六进制
UNHEX() 是唯一能在 INSERT/UPDATE 中还原原始二进制的 SQL 内置方式
不能靠客户端拼 0x616263 或 X'616263' —— 这些语法只接受字面量,无法绑定参数;也不能靠应用层 base64,因为 MySQL 没有原生 FROM_BASE64()(8.0+ 才有,且不处理 NUL)。
-
UNHEX(@hex_str)可以安全接变量,支持预处理语句,返回类型是BINARY,与目标字段类型完全对齐 - 输入必须是偶数长度、只含合法十六进制字符,否则返回
NULL(不是报错),这点要提前校验,否则静默丢数据 - 别写
UNHEX(HEX(col))做无意义转换:虽然结果一致,但多一次函数调用 + 多一倍内存拷贝,对大 BLOB 影响明显
常见踩坑:HEX/UNHEX 在 UUID 场景下的误用
很多人用 UNHEX(REPLACE(uuid(), '-', '')) 存 UUID,却忽略两个关键点:
-
uuid()返回的是带连字符的字符串,REPLACE后是 32 位十六进制字符串,UNHEX()能正确转成 16 字节BINARY(16)—— 这没问题 - 但反过来查时,如果写
WHERE id_bin = UNHEX('...'),MySQL 无法利用索引(因为UNHEX()是函数,导致索引失效);正确做法是把查询值先算好再传参,或用生成列 + 索引 - 更隐蔽的坑:
HEX(id_bin)输出是大写,而uuid()默认小写;若用字符串比较(比如HEX(id_bin) = 'abc...'),大小写敏感,可能漏匹配
真正容易被忽略的,是 HEX/UNHEX 的「上下文切换」:它们在 SQL 层完成编码/解码,不经过客户端字符集转换,也不受 sql_mode 影响 —— 但这也意味着,一旦你 mix 了 CONVERT(... USING ...) 或隐式字符集转换,结果就不可控了。所以全程保持字段类型明确(BINARY / VARBINARY)、不依赖默认行为,比追求“快”重要得多。











