Oracle数据库的字符集问题,也涉及作为服务器操作系统的CentOS或者Windows的字符集与Oracle字符集之间的关联关系
Oracle的字符集,这个问题的提出是因为两个原因:
一是遇到一个DMP文件需要恢复到数据库中去,而这个DMP文件的字符集是US7ASCII,
第二个是系统上安装Oracle已经能成功,
但是被中文英文系统字符集等问题搞得有点头大。
Oracle数据库的字符集问题不算是大问题,但也是一个头疼的问题。
这是因为有这么三个原因:
一是Oracle数据库在安装时指定好字符集之后一般不能更改,
二是字符集问题涉及服务器与客户端之间的存取问题,
三是Oracle数据库迁移时也会跟字符集非常相关。
清楚Oracle字符集的相关问题,则要先理清数据库运行过程中的架构以及在这个架构中的字符集设置及这些设置之间的关联关系。
服务器与客户端分开,客户端用应用程序比如sqlplus或者PL/SQL与服务端相连。
服务端有两个字符集:服务端操作系统字符集、服务端数据库字符集;
客户端有一个字符集:客户端操作系统字符集;
客户端有一个参数:操作系统参数NLS_LANG。
这三个字符集与一个参数中,有一个字符集对整个架构的运行没有影响,它就是服务端操作系统字符集,所以这个字符集将不再出现在我们的讨论过程中。为什么这个服务端操作系统字符集没有用呢?
这是因为Oracle在存取字符时与客户端进行字符集确认与转码的过程是由Oracle数据库自身完成的,
不需要经过Oracle数据库所在的服务器的帮助。
具体的是怎么回事用以下例子说明一下。
比如在Oracle数据库中有一个表,用如下语句创建:
create table test(name varchar2(10));
为了说明问题假定有这样的一个环境:
服务器端Oracle数据库的字符集是UTF8,客户端操作系统字符集是ZHS16GBK,客户端NLS_LANG参数设置为ZHS16GBK。
那么从客户端应用程序(比如sqlplus)发出这样一条命令:
insert into test (name) values('中国');
首先,这里有一个字符串“中国”,客户端操作系统用ZHS16GBK对它进行编码,比如编成“167219”,并把它交给sqlplus程序,然后把它发送给Oracle数据库。接着,Oracle数据库收到一串编码“167219”,不是直接往数据库里一扔就完事的,它要问客户端操作系统:“请问你给我的这串代码是用什么格式编码的啊?”客户端操作系统怎么回答?它会这么回答:“编码格式请参照参数NLS_LANG”。Oracle数据库一看,NLS_LANG='ZHS16GBK',这个编码格式与Oracle数据库自身的编码格式“UTF8”不一样,然后就是Oracle数据库发挥自己专长的地方了,为什么呢?
因为Oracle数据库有它自己的编码表,而且不是一张而是好多张编码表,它可以根据编码表对编码进行翻译和转码。
这就好比Oracle数据库是一个翻译,它会好几国语言,牛人一个。
像上面的这个情况,Oracle会把“167219”这串代码拿过来,根据参数NLS_LANG查ZHS16GBK编码表,
找到对应这串代码的字符“中国”,然后再到UTF8编码表中查“中国”对应的编码,比如查到的结果是“3224678”。
最后,将转码之后的编码“3224678”存放到Oracle数据库中去。
为了进一步说明问题,我们再执行一条语句:
select name from test;
首先,Oracle数据库会从数据库中取出一串代码“3224678”。
接着,Oracle数据库不是直接把这串代码交给sqlplus程序,它会多问一句:“代码串我是取出来了,它是UTF8编码格式的,
请问sqlplus,你希望要什么编码格式的?”,sqlplus仍然会很爽快地告诉Oracle数据库:“编码格式请继续参照参数NLS_LANG”。
Oracle数据库一看,ZHS16GBK跟UTF8又不一样,所以先查UTF8编码表,找到编码“3224678”对应的字符“中国”,
再查ZHS16GBK编码表,找到“中国”对应的编码“167219”,然后就是把最后得到的这串编码“167219”交给sqlplus程序。
最后,sqlplus直接把得到的这串编码扔给客户端操作系统,而操作系统只有ZHS16GBK编码表,它不会问得到的这串编码是什么格式的,只会直接到ZHS16GBK编码表中去查“167219”对应的字符是什么,并把它交给应用程序显示出来。这个显示的结果是“中国”。
以上就是一个完整的从客户端编码并经过Oracle数据库转码存入数据库,然后从数据库取出并转码交给客户端显示的实验。
从以上过程我们可以得出以下一些结论:
1.对Oracle数据库存取起作用的是这些:客户端操作系统字符集、客户端操作系统参数NLS_LANG、服务端数据库字符集。
2.对Oracle数据库不起作用的是服务端操作系统字符集。
3.客户端操作系统只有一张编码表,与客户端字符集对应。
4.Oracle数据库的字符集只有一个,并且固定,一般不改变。
5.存放在Oracle数据库中的字符串的编码格式只有一个,它就是数据库的字符集所对应的编码格式。
6.Oracle数据库有很多张编码表,可以在数据存入时将其它编码格式的编码转换为数据库字符集指定的格式,
 取出时从数据库字符集指定的格式转换为其它编码格式。
7.整个架构中的转码只发生在Oracle数据库边界上,其它地方没有。
8.Oracle是根据客户端操作系统的参数NLS_LANG与自己的字符集进行对照来确定是否需要进行转码的。
最最重要的结论出来了:
9.Oracle数据库如何选择字符集?只有一个原则,
那就是这个字符集要包含数据库运行过程中所能存入的数据字符,
通常作为中国人我们选择ZHS16GBK,如果想再保险一点,选择AL32UTF8。
10.服务器操作系统选择什么字符集?这个字符集与数据库字符集一点关系都没有,
只跟谁有关?操作系统管理员!所以它的选择原则是,系统管理员想选择什么就选择什么。
11.客户端操作系统选择什么字符集?我是中国人,我用中文操作系统,
   所以我选择ZHS16GBK。建议中国人都选择ZHS16GBK。
12.客户端操作系统参数NLS_LANG参数如何设置?这个只有一个设置方法,
   那就是与操作系统字符集相同。要不然会出问题的……
最最最最重要的一句话:
最好的,最不容易出字符集错误的就是:将数据库字符集、客户端字符集、客户端操作系统NLS_LANG参数三个地方作同样的设置。
另外再记录一下EXP和IMP过程与字符集相关的事情。

EXP时,起作用的有Oracle数据库的字符集和客户端操作系统参数NLS_LANG两项,
这时服务器与客户端操作系统字符集都不起作用。
如果客户端操作系统参数NLS_LANG与Oracle数据库的字符集相同,那就直接导出,不需要转码,
并且导出文件的字符集与上述两项一样;
如果客户端操作系统参数NLS_LANG与Oracle数据库的字符集不同,
那么导出时Oracle数据库会将数据文件从Oracle数据库的字符集编码格式转码成客户端操作系统参数NLS_LANG指定的编码格式。
总而言之一句话:导出文件的字符集格式与导出客户端操作系统参数NLS_LANG一定相同。
IMP时,起作用的仍然是两项,一项是DMP文件第二第三字节指定的字符集,另外一项是Oracle数据库的字符集。
两个相同就不需要转码,两个不同就转成Oracle数据库字符集指定的编码格式。
最后记录几个问题。
1.DMP文件是US7ASCII字符集,要把它导入字符集是ZHS16GBK的数据库中去,如何操作?
第一步:安装一个US7ASCII字符集的数据库(比如说9i);
第二步,将DMP文件导入该数据库;
第三步,设置导出客户端操作系统参数NLS_LANG=ZHS16GBK,然后导出;
第四步,将后导出的DMP文件导入字符集是ZHS16GBK的数据库中去。理论上成功。需要做实验测试。
2.曾经说到,一般情况下数据库的字符集在数据库安装好之后就不可以更改。那么如果万一领导说一定要改,怎么办?
比如说原来的字符集是ZHS16GBK,非要让转成UTF8,有没有办法?
答案是有的,但是,但是不一定会全部成功,这里有一个严格超集的概念,这个概念在这篇文章里不讲。
答案是这么做,设置导出客户端操作系统参数为UTF8,然后导出,这里,数据编码格式会从ZHS16GBK转码成UTF8,
然后再删除ZHS16GBK的数据库,新建一个UTF8的数据库,再导入就可以了。

oracle中导入dmp字符乱码分析和解决方案

oracle字符集
Oracle字符集是一个字节数据的解释的符号集合,有大小之分,有相互的包容关系。
ORACLE支持国家语言的体系结构允许你使用本地化语言来存储,处理,检索数据。
它使数据库工具,错误消息,排序次序,日期,时间,货币,数字,和日历自动适应本地化语言和平台。
影响oracle数据库字符集最重要的参数是NLS_LANG参数。它的格式如下:
NLS_LANG = language_territory.charset
它有三个组成部分(语言、地域和字符集),每个成分控制了NLS子集的特性。其中:
Language指定服务器消息的语言,territory 指定服务器的日期和数字格式,charset 指定字符集。
如:AMERICAN _ AMERICA. ZHS16GBK。
从NLS_LANG的组成我们可以看出,真正影响数据库字符集的其实是第三部分。
所以两个数据库之间的字符集只要第三部分一样就可以相互导入导出数据,前面影响的只是提示信息是中文还是英文。
如何查询Oracle的字符集
1、查询oracle server端的字符集
有很多种方法可以查出oracle server端的字符集,比较直观的查询方法是以下这种:
SQL>select userenv('language') from dual;
结果类似如下:AMERICAN _ AMERICA. ZHS16GBK
或:
SQL>select userenv('language') from dual;
USERENV('LANGUAGE')
----------------------------------------------------
SIMPLIFIED CHINESE_CHINA.ZHS16GBK
2、如何查询dmp文件的字符集
用oracle的exp工具导出的dmp文件也包含了字符集信息,dmp文件的第2和第3个字节记录了dmp文件的字符集。
如果dmp文件不大,比如只有几M或几十M,(这里推荐一个工具  Toad  可以使用这个工具打开 dmp文件)
可以用UltraEdit打开(16进制方式,看第2第3个字节的内容,如0354,然后用以下SQL查出它对应的字符集:
SQL> select nls_charset_name(to_number('0354','xxxx')) from dual;
结果是: ZHS16GBK
3、查询oracle client端的字符集
在windows平台下,就是注册表里面HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME0\NLS_LANG

或  HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\ORACLE\KEY_OraClient10g_home4(我电脑)

如果检查的结果发现server端与client端字符集不一致,请统一修改为同server端相同的字符集。
三、修改oracle的字符集
1、修改server端字符集(我试过的)
若此时数据库服务器已启动,则先执行SHUTDOWN IMMEDIATE命令关闭数据库服务器,然后执行以下命令:
SQL>STARTUP MOUNT;
SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;
SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;
SQL>ALTER DATABASE OPEN;
SQL>ALTER DATABASE CHARACTER SET INTERNAL_USE ZHS16GBK(这里为你所要转换成的字符集); //跳过超子集检测
SQL>ALTER DATABASE national CHARACTER SET INTERNAL ZHS16GBK(这里为你所要转换成的字符集);
执行后出错ORA-00933: SQL 命令未正确结束,不过执行上一行命令已经生效,这一句出错对修改似乎没有影响。
下面关闭数据库,然后重新启动:
  SQL>SHUTDOWN IMMEDIATE;
  SQL>STARTUP
2、修改dmp文件字符集(这个我没有试,借鉴来的)
具体的修改方法比较多,最简单的就是直接用UltraEdit修改dmp文件的第2和第3个字节。
比如想将dmp文件的字符集改为ZHS16GBK,可以用以下SQL查出该种字符集对应的16进制代码:
SQL> select to_char(nls_charset_id('ZHS16GBK'), 'xxxx') from dual;
结果是:0354
然后将dmp文件的2、3字节修改为0354即可。
3. 修改客户端的文件字符集和新配置一个环境变量:
1修改客户端字符集:
运行regedit命令,在注册表中找到这个下的键HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME0\NLS_LANG
将其值改为上述服务器端你所修改的字符编码值。
2 新配置一个环境变量
点击我的电脑右键》属性》高级》环境变量》新建一个用户变量,其变量名是:NLS_LANG;
变量值是:SIMPLIFIED CHINESE_CHINA.WE8ISO8859P1(这里的字符集和你在服务器端和客户端修改的字符集必须一致)。
注意:最后一定要重启oracle的主服务!不然乱码问题依旧存在.
总结:一般将数据库服务器端,客户端,还有新配置的环境变量的值修改成和dmp文档一样的字符集就可解决乱码的问题!
解决方案:
在导入DMP文件前,在客户端导入与服务器一致的环境变量。
例如:export NLS_LANG=American_America.ZHS16GBK

备注:随笔中内容来源于网上资料整理,仅供参考。

Oracle数据库字符集问题的更多相关文章

  1. oracle数据库字符集的修改

    本文摘自:http://blog.csdn.net/nsj820/article/details/65711051.改客户端字符集:通过WINDOWS的运行菜单运行Regedit,修改注册表 Star ...

  2. 选择ORACLE数据库字符集

    如何选择数据库的字符集是一个有争议的话题,字符集本身涉及的范围很广,它与应用程序.客户的本地环境.操作系统.服务器等关系很密切,因此要做出合适的 选择,需要明白这些因素之间的关系.另外对字符集的基本概 ...

  3. linux下oracle数据库字符集修改

    linux下oracle数据库字符集修改 0.RHEL6.7.oracle11gr2 1.登录oracle.在安装oracle的用户下进入数据库. $ sqlplus / as sysdba 2.查询 ...

  4. Oracle数据库字符集问题解析

    Oracle数据库字符集问题解析 经常看到一些朋友问ORACLE字符集方面的问题,我想以迭代的方式来介绍一下.第一次迭代:掌握字符集方面的基本概念.有些朋友可能会认为这是多此一举,但实际上正是由于对相 ...

  5. ORACLE数据库字符集处理

    简介: ORACLE数据库字符集,即Oracle全球化支持(Globalization Support),或即国家语言支持(NLS)其作用是用本国语言和格式来存储.处理和检索数据.利用全球化支持,OR ...

  6. Oracle数据库字符集修改

    Oracle字符集是一个字节数据的解释的符号集合,有大小之分,有相互的包容关系.ORACLE支持国家语言的体系结构允许你使用本地化语言来存储,处理,检索数据.一般来说,数据库字符集在安装数据库实例时就 ...

  7. Linux下修改Oracle数据库字符集命令

    常见情形:从服务器备份Oracle数据库后再到本地机器上还原Oracle数据库的时候经常会碰见数据库字符编码不一致的情况,可以用以下命令来修改本地的Oracle数据库字符编码,然后顺利还原Oracle ...

  8. oracle数据库字符集查询

    1>数据库服务器字符集 select * from nls_database_parameters,其来源于props$,是表示数据库的字符集. 查询结果如下 NLS_LANGUAGE AMER ...

  9. oracle数据库字符集

    Oracle字符集的基本原理 1. Oracle服务器字符集 oracle以哪种字符编码存储字符,可以通过以下语句查出数据库字符集的设置. 方法1 SQL> select * from v$nl ...

随机推荐

  1. R语言实现金融数据的时间序列分析及建模

    R语言实现金融数据的时间序列分析及建模 一 移动平均    移动平均能消除数据中的季节变动和不规则变动.若序列中存在周期变动,则通常以周期为移动平均项数.移动平均法可以通过数据显示出数据长期趋势的变动 ...

  2. oracle 11g 数据库恢复技术 ---02 控制文件

    oracle 11g 数据库恢复技术 ---02 控制文件 SYS@ orcl >show parameter control_file NAME TYPE VALUE ------------ ...

  3. 16/7/7_PHP-Static静态关键字

    Static静态关键字 静态属性与方法可以在不实例化类的情况下调用,直接使用类名::方法名的方式进行调用.静态属性不允许对象使用->操作符调用. class Car { private stat ...

  4. WordPress致命错误 紧急处理代码

    将下面代码添加到当前主题函数模板 functions.php 中: dadd_filter( 'wp_fatal_error_handler_enabled', '__return_false' );

  5. MYSQL5.5 linux 多实例

    安装过程 cmake 安装参照上一篇 https://www.cnblogs.com/lixuchun/p/9240888.html 多实例采用 /data 目录作为mysql多实例的总的根目录,然后 ...

  6. 在layui中,新的页面怎么获取另一个页面传过来的数据,并可以对数据进行判断,layui中的后台分页(table)。

    例如:打开一个新页面的同时,传数据. layer.open({ type: 2, title: '新增项目', shadeClose: false, shade: [0.3], maxmin: tru ...

  7. [Markdown] 01 简单应用 第一弹

    目录 0. "调用函数前必先声明" 0.1 Table of Content 0.2 分割线 0.3 引用 0.4 标记 0.5 关于 html 0.6 代码块 用法 1 用法 2 ...

  8. dp(买票优惠)

    CodeForces - 1154F There are n shovels in the nearby shop. The i-th shovel costs ai bourles. Misha h ...

  9. ssh_exchange_identification: read: Connection reset by peer解决办法

    使用本地终端连接centos服务器,提示ssh_exchange_identification: read: Connection reset by peer $ssh root@10.xxx.xxx ...

  10. java 快速开发平台 有代码生成器 springmvc SSM后台框架源码

    .   权限管理:点开二级菜单进入三级菜单显示 角色(基础权限)和按钮权限      角色(基础权限): 分角色组和角色,独立分配菜单权限和增删改查权限.      按钮权限: 给角色分配按钮权限.2 ...