Oracle导入US7ASCII编码导出的DMP时中文乱码问题咨询
问题产生原因
- US7ASCII是Oracle定义的7位基础英文字符集,仅支持0-127编码位的标准ASCII字符,本身没有任何中文字符的编码映射规则。
- 不少场景下客户端和服务端同时配置US7ASCII存储中文,本质是利用了Oracle字符集一致时跳过编码校验、直接透传字节的逻辑,把GBK/UTF8格式的中文多字节内容硬塞进数据库,属于非合规的存储方式,数据库本身不会对这些高位字节(大于127的字节)做校验和转码。
- 用US7ASCII编码配置执行导出时,exp/expdp进程会按照US7ASCII的编码规则处理所有内容:所有大于127的高位字节会被判定为无效字符,直接被转成问号
?或者直接截断,同时dmp文件头会标记导出字符集为US7ASCII。这个字节损坏的过程发生在导出阶段,后续导入时无论怎么调整NLS_LANG参数、怎么配置目标库字符集,拿到的都是已经被破坏的中文内容,自然会出现乱码。
对应解决办法
按当前场景选对应方案即可:
- 若还未执行导出操作:导出前先把客户端
NLS_LANG参数配置为和数据库实际存储中文的编码一致,比如存储中文用GBK就设为NLS_LANG=AMERICAN_AMERICA.ZHS16GBK,用UTF8就设为NLS_LANG=AMERICAN_AMERICA.AL32UTF8,再执行导出命令,得到的dmp文件会完整保留中文原始字节,导入时只要字符集匹配就不会出现乱码。 - 若已经用US7ASCII导出了dmp,但还能正常连接原数据库:直接废弃已经导出的dmp文件,按照上面的正确字符集配置重新导出备份再执行导入,这是零数据损坏的最稳妥方案。
- 若原数据库已经无法连接,仅留存US7ASCII导出的dmp文件:用16进制编辑器打开dmp文件,修改文件头处记录的字符集ID字段,把US7ASCII对应的ID
0x0001改成实际存储中文的字符集ID(ZHS16GBK对应0x0354,AL32UTF8对应0x0369),修改完成后导入时把客户端NLS_LANG和目标库字符集都配置为修改后的对应字符集,可恢复大部分未被转码破坏的中文内容。
注意:如果导出阶段已经有部分中文高位字节被转成了
0x3F(即问号字符),这部分内容属于不可逆损坏,无法通过修改字符集配置恢复。
内容的提问来源于stack exchange,提问作者ShaoLong Liu
相关产品推荐
相关产品推荐

