专栏首页数据和云【Oracle字符集】识别及转换导出文件的字符集

【Oracle字符集】识别及转换导出文件的字符集

编辑手记:很多人在进行数据库导入导出操作的时候会遇到字符集的问题,今日拣选了 《循序渐进Oracle》一书中的相关章节,希望对初学Oracle的朋友有所帮助。

在传统的EXP导出文件中,记录着导出使用的字符集id,通过查看导出文件头的第2、3个字节,我们可以找到十六进制表示的字符集ID,在Windows上,可以使用UltraEdit等工具打开dmp文件,查看其导出字符集,如图所示:

在UNIX环境上,可以通过以下命令来查看(以下范例来自Solaris平台):

cat expdat.dmp | od -x | head

需要注意的是,在不同平台,以上命令的输出可能有所不同,比如在Linux平台:

[oracle@jumper oracle]$ cat a.dmp |od -x |head -2 0000000 0303 4554 5058524f3a54 3156 2e30 3230 0000020 302e0a31 4544 4759454c520a41544c42

这是由于Solaris和Linux的字节序是不同的,Solaris是Big-Endians,Linux是Little-Endians,所以Linux上的输出通过交换可以得到:

0303 5445 58504f52 ….

字符集和Solaris上是一致的,所以也可以通过od的参数设置显示格式:

[oracle@jumper oracle]$ cat a.dmp|od -t x1|head -2 0000000 03 03 54 45 58 504f52 543a56 31 30 2e 30 32 0000020 2e 30 310a44 45 59 474c450a52 54 41 424c

Oracle提供标准函数,对字符集名称及ID进行转换:

SQL> selectnls_charset_id('ZHS16GBK') from dual; NLS_CHARSET_ID('ZHS16GBK') -------- 852 SQL> select nls_charset_name(852) from dual; NLS_CHAR -------- ZHS16GBK

十进制转换十六进制,即可获得字符集的编码:

SQL> select to_char('852','xxxx') from dual; TO_CH ----- 354

对应前两张图 第2、3字节,就知道该导出文件字符集为ZHS16GBk。查询数据库中有效的字符集可以使用以下脚本:

col nls_charset_id for 9999 col nls_charset_name for a30 col hex_id for a20 select nls_charset_id(value) nls_charset_id, value nls_charset_name,to_char(nls_charset_id(value), 'xxxx') hex_id from v$nls_valid_values where parameter = 'CHARACTERSET' order by nls_charset_id(value);

输出样例如下:

而对于Oracle 10g的expdp导出文件,一切则要简单得多,在expdp的导出文件开始部分,Oracle以XML格式记录了数据的字符集信息,以下是一个单表导出文件的头信息。

在文件开始部分就记录了数据库的字符集、国家字符集及时区等信息,在表字段的属性部分也记录了字符集ID:

对于传统的DMP导出文件,在很多时候,当进行导入操作时,已经离开了源数据库,这时如果目标数据库的字符集和导出文件不一致,多半就需要进行特殊处理进行转换。最常见的转换发生在从US7ASCII到ZHS16GBK之间。

由于很多数据库最初以US7ASCII字符集存储中文,单纯通过导出导入是无法完成字符集转换的。对于这种情况,可以通过设置导出字符集为US7ASCII,原样导出数据;导出后修改导出文件的第二、三字符,修改0001为0354,这样就可以将US7ASCII字符集的数据正确导入到ZHS16GBK的数据库中。

如图所示是一个测试例子,我们可以通过UltraEdit等工具的二进制编辑模式修改导出文件:

修改完成之后,可以导入修改后的DMP文件:

E:\nls2>set NLS_LANG=AMERICAN_AMERICA.ZHS16GBK E:\nls2>imp eygle/eygle file=Sus7ascii-Cus7ascii-exp817.dmp fromuser=eygle touser=eygle tables=test Export file created by EXPORT:V08.01.07via conventional path import done in ZHS16GBK character set and AL16UTF16 NCHAR character set export server uses UTF8 NCHAR character set (possible ncharset conversion) . . importing table "TEST" 2 rows imported Import terminated successfully without warnings.

通过这种方式,最终中文可以被正常导入ZSH16GBK的数据库:

另外一种可以尝试的方法是使用create database命令。如果导出文件使用的字符集是US7ASCII,目标数据库的字符集是ZHS16GBK,就可以使用create database的方法来修改,具体操作如下:

然后可以导入数据:

E:\nls2>set nls_lang=AMERICAN_AMERICA.US7ASCII E:\nls2>imp eygle/eygle file=Sus7ascii-Cus7ascii.dmp fromuser=eygle touser=eygle Export file created by EXPORT:V09.02.00via conventional path import done in US7ASCII character set and AL16UTF16 NCHAR character set import server uses ZHS16GBK character set (possible charset conversion) . . importing table "TEST" 2 rows imported Import terminated successfully without warnings.

查询导入数据:

E:\nls2>sqlplus eygle/eygle SQL> select * from test; NAME ---------- 测试 test

当发出“create database character set us7ascii;”命令时,数据库v$nls_parameters中的字符集设置随之更改,该参数影响导入进程,更改后可以正确导入数据,重起数据库后,该设置恢复。

提示:v$nls_paraemters来源于x$nls_parameters,该动态性能视图影响导入操作;而nls_database_parameters来源于props$数据表,影响数据存储。以上的方法只应该在不得已的情况下使用,其本质是欺骗数据库,强制导入数据,但是可能会损失元数据。

本文分享自微信公众号 - 数据和云(OraNews),作者:盖国强

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-01-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 循序渐进Oracle:数据库的字符集和字符集文件

    导读:本文来自『墨天轮』专栏“循序渐进Oralcle”(https://www.modb.pro/topic/6289,复制到浏览器中打开或者点击“阅读原文”)...

    数据和云
  • 【云和恩墨大讲堂】复合索引与绑定变量

    讲师简介 ? 邓秋爽(小鱼) 云和恩墨专家,有超过5年超大型数据库专业服务经验,擅长oracle 数据库优化、SQL优化和troubleshooting 今晚的...

    数据和云
  • 案例详解:Linux文件系统异常导致数据库文件无法访问

    墨墨导读:某客户单位数据库出现异常,大致现象是:数据库状态是open的,但是其中一个数据文件无法访问,本文分享排查原因与解决问题的整个过程。

    数据和云
  • 使用DNS名称作为安全性依据的漏洞优化

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    chenchenchen
  • 小记 | 再次登上学生时代的个人博客,泪目

    虽然才毕业不到半年,但是由于大三时鱼皮就开始外出实习,很少在学校。再加上最后一个学期因为疫情影响无法返校,因此鱼皮对学校的记忆已经比较模糊了。

    程序员鱼皮
  • 使用QtScript库解析Json数组例子

    本文转载自:http://blog.sina.com.cn/s/blog_671732440100uwxh.html

    ccf19881030
  • 推荐收藏 | 一个画出高大上的机器学习图的神器scikit-plot

    https://github.com/reiinakano/scikit-plot

    Sam Gor
  • 表扫描描述符及扫描方向

    1、表扫描函数的参数传递通过TableScanDescData,函数内层将扫描到的记录存储到HeapScanDesc.rs_ctup中,然后将该成员内容传递给s...

    yzsDBA
  • 协议森林07 傀儡 (UDP协议)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁任何形式转载。 我们已经讲解了物理层、连接层和网络层。最开始的连接层协议种...

    Vamei
  • 马化腾:王者荣耀玩得比较少 吃鸡游戏是当前重点

    12月4日下午消息,第四届世界互联网大会于2017年12月3日—5日在浙江省乌镇举行,在今日下午企业家代表集体采访中,腾讯董事会主席兼首席执行官马化腾表示,腾讯...

    企鹅号小编

扫码关注云+社区

领取腾讯云代金券