hex()对整数返回其十六进制表示(如hex(255)='ff'),对字符串返回字节的十六进制编码(如hex('abc')='616263');unhex()仅接受偶数长度十六进制字符串,否则返回null;推荐用conv()进行数值进制转换以避免歧义。

HEX() 函数把数字转成16进制字符串,但要注意输入类型
HEX() 对整数和字符串行为完全不同:传入整数(如 10)时,它返回该数的十六进制表示('A');传入字符串(如 'abc')时,则返回其字节的十六进制编码('616263')。容易踩的坑是误以为 HEX(255) 会返回 'FF' —— 实际上它确实返回 'FF',但 HEX(256) 返回的是 '100'(不是 '0100'),即无前导零、不补位。
常见错误现象:用 HEX() 处理主键 ID 后再想反向还原,结果发现字符串长度不固定,导致 UNHEX() 解码失败。
- 对纯数值转换,确保输入是
UNSIGNED INTEGER类型,避免负数触发意外行为(MySQL 8.0+ 中负数会转成补码形式,如HEX(-1)→'FFFFFFFFFFFFFFFF') - 若需固定长度(如 8 位十六进制),用
LPAD(HEX(n), 8, '0') - 不要对浮点数直接用
HEX()—— 它会先隐式转为整数截断,HEX(3.14)得到'3'
UNHEX() 只接受偶数长度的十六进制字符串
UNHEX() 的输入必须是偶数个十六进制字符(0-9、A-F、a-f),否则返回 NULL,且不会报错。这是最常被忽略的兼容性陷阱。
使用场景比如:从 URL 参数或日志中拿到形如 'a1b2' 的 hex 字符串,想还原为原始字节或整数。
- 检查长度:
CHAR_LENGTH(hex_str) % 2 = 0是调用UNHEX()前的必要校验 - 小写/大写均可,
UNHEX('FF')和UNHEX('ff')结果一致 -
UNHEX('')返回空二进制值(''),不是NULL;但UNHEX(NULL)返回NULL - 若原始数据是整数,记得后续用
CONV(HEX(val), 16, 10)这类方式还原,而不是指望UNHEX()直接吐出数字
数值 ↔ 十六进制互转的可靠组合:CONV() 比 HEX()/UNHEX() 更可控
当目标明确是「整数进制转换」而非「二进制编码」,CONV() 更合适:CONV(n, 10, 16) 得十六进制字符串,CONV(hex_str, 16, 10) 得十进制整数。它不关心字节边界,也不强制偶数长度。
性能影响很小,但语义清晰——尤其适合 ID 加密、短链生成等需要确定长度和进制逻辑的场景。
-
CONV(255, 10, 16)→'FF';CONV('FF', 16, 10)→255 - 输入非合法十六进制字符(如
'FG')时,CONV()在遇到非法字符处截断,返回已解析部分(CONV('FG', 16, 10)→15),不是NULL,需配合LENGTH()校验是否完整转换 - 最大支持 64 位整数,超出部分会被静默截断(
CONV('10000000000000000', 16, 10)在 32 位系统上可能失真)
实际应用中别混淆「编码」和「进制表示」
很多人想用 HEX() 把用户 ID 转成“看起来更安全”的字符串,结果发现 UNHEX() 还原不了——问题往往出在:原始 ID 是整数,但 HEX(id) 输出的是数值的十六进制形式,而他们误当成字节序列去解码。
例如:id = 255 → HEX(255) = 'FF',此时 UNHEX('FF') 返回的是单字节 0xFF(二进制值 255),看着像能还原;但 id = 256 → HEX(256) = '100',UNHEX('100') 因长度为奇数直接返回 NULL。
- 如果目的是隐藏 ID,用
CONV(id, 10, 36)(36 进制)或加盐哈希更稳妥 - 如果真要走二进制路径,先统一转为定长字节数(如
LPAD(HEX(id), 8, '0')),再UNHEX() - 所有涉及
UNHEX()的地方,务必在 SQL 中加WHERE CHAR_LENGTH(hex_col) % 2 = 0过滤,否则 JOIN 或 WHERE 条件可能因NULL行失效











