utl_raw.cast_to_raw和cast_to_varchar2仅做字节级映射,不转换字符集;跨字符集需用utl_i18n.string_to_raw/raw_to_char;hextoraw/rawtohex要求输入为偶数位十六进制字符串。

直接说结论:UTL_RAW.CAST_TO_RAW 和 UTL_RAW.CAST_TO_VARCHAR2 是最常用、最轻量的字符串 ↔ RAW 转换方式,但它们不处理字符集转换,只做字节级映射;若需跨字符集(如 GBK → UTF8),必须用 UTL_I18N.STRING_TO_RAW / RAW_TO_CHAR。
UTL_RAW.CAST_TO_RAW 为什么不能当“编码转换器”用
这个函数本质是把输入字符串每个字符的当前数据库字符集编码值(比如 AL32UTF8 下的 UTF-8 字节序列)逐字节拷贝进 RAW,不做任何解释或重编码。常见误用场景:
- 数据库字符集是 AL32UTF8,执行
UTL_RAW.CAST_TO_RAW('中文')→ 得到C4E3BAC4(UTF-8 编码的 4 字节) - 数据库字符集是 ZHS16GBK,同样语句 → 得到
D6D0CEC4(GBK 编码的 4 字节) - 如果把前者结果误当成 GBK 编码再用
UTL_RAW.CAST_TO_VARCHAR2解,会乱码
所以它适合:同一数据库内做二进制暂存、MD5 值拼接、RAW 列写入等不涉及字符集切换的操作。
HEXTORAW 和 RAWTOHEX 的边界条件必须守牢
这两个函数专用于十六进制字符串 ↔ RAW 的互转,但对输入格式极其敏感:
-
HEXTORAW('abc')合法,长度为偶数,每两位解析为一个字节 →AB C?不,实际是AB+C??错 —— 它会报ORA-01465: invalid hex number,因为'abc'是 3 位,奇数 - 正确写法必须是偶数位:
HEXTORAW('ab')、HEXTORAW('abcd')、HEXTORAW('ABCDEF0123456789') -
RAWTOHEX输出永远是大写、无前缀、偶数位字符串,比如RAWTOHEX(HEXTORAW('aabb'))返回AABB,不是0xaabb或aabb - 注意:空字符串
''经HEXTORAW后返回NULL,不是空 RAW
UTL_I18N.STRING_TO_RAW 需要提前确认字符集支持范围
这个函数才真正做“按目标字符集重新编码”,但它依赖底层字符集库是否启用:
- 若数据库是 UTF8 库,
UTL_I18N.STRING_TO_RAW('test', 'BIG5')可成功;但若数据库是 GBK 库,同样调用会返回NULL,且不报错 - 常见安全字符集组合:
STRING_TO_RAW(str, 'AL32UTF8')在几乎所有库中都可用;STRING_TO_RAW(str, 'ZHS16GBK')仅在 GBK 库中可靠 - 参数
TO_CHARSET为空时,等价于当前数据库字符集,不是系统默认值 —— 这个行为容易被忽略,导致开发环境和生产环境结果不一致 - 输入字符串含 NULL 字符(
CHR(0))时,整个转换会截断到第一个 NULL,不是报错
性能差异和选型建议
三类转换路径性能排序(从快到慢):
-
UTL_RAW.CAST_TO_RAW≈UTL_RAW.CAST_TO_VARCHAR2:纯内存拷贝,无字符集查表,最快 -
HEXTORAW/RAWTOHEX:需逐两位解析/格式化,中等开销,但稳定 -
UTL_I18N.STRING_TO_RAW/RAW_TO_CHAR:触发完整字符集转换引擎,尤其多字节字符(如中文)时开销明显上升
真实项目里,90% 的场景其实只需要 CAST_TO_RAW + RAWTOHEX 组合;只有明确要导出为 BIG5 文件、对接旧系统 GBK 接口、或做国际化日志编码时,才值得引入 UTL_I18N 并验证字符集库配置。
最容易被忽略的一点:UTL_I18N 包在某些 Oracle 版本中默认未安装,首次使用前得先运行 SP_CREATE_SYSTEM_PACKAGES(1, 'UTL_I18N'),否则直接报 PLS-00201: identifier 'UTL_I18N.STRING_TO_RAW' must be declared —— 这个错误不提示缺包,只提示函数不存在。











