日期:2014-05-16  浏览次数:20361 次

Oracle字符集导致的乱码
“项目部署在日文操作系统中,原有的基础数据的部分中文字符在Browser显示为乱码,咱们还是把中文都翻译成日文吧!”我们测试的同事说道。乍听到,我觉得在中文的OS上能正常显示人家日文字符,反过来应该也是没问题的才对啊,翻译成日文的做法不太理智。所以提出应该是字符集的问题。通过日文系统访问别的网站没有出现我们的情况,并且看到winXP默认支持东亚语言体系,排除了OS字符集缺失的可能。才将问题定位到数据库上(数据库服务器和应用服务器同机)。随即修改了props$表的字符集设置,结果导致JDBC无法连接,所以才找到了下面的服务端修改步骤:

1、修改server端字符集(不建议使用)
     在oracle 8之前,可以用直接修改数据字典表props$来改变数据库的字符集。但oracle8之后,至少有三张系统表记录了数据库字符集的信息,只改props$表并不完全,可能引起严重的后果。正确的修改方法如下:

   $sqlplus /nolog
 SQL>conn / as sysdba;
   -- 若此时数据库服务器已启动,
   -- 则先执行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 YourCharset;
 SQL>ALTER DATABASE national CHARACTER SET YourCharset; -- 该步可不执行,此为Nvarchar、Nchar数据存储编码方式
 SQL>SHUTDOWN IMMEDIATE;
 SQL>STARTUP

 注意:如果没有大对象,在使用过程中进行语言转换没有什么影响,
  (切记设定的字符集必须是ORACLE支持,不然不能start) 按上面的做法就可以,但是可能会出现‘ORA-12717: Cannot ALTER DATABASE NATIONAL CHARACTER SET when NCLOB data exists’这样的提示信息,要解决这个问题有两种方法

 一个是,利用INTERNAL_USE 关键字修改区域设置,还有一个是利用re-create,但是re-create有点复杂,所以请用internal_use,

 SQL>SHUTDOWN IMMEDIATE;
 SQL>STARTUP MOUNT EXCLUSIVE;
 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 NATIONAL CHARACTER SET INTERNAL_USE YourCharset;
 SQL>SHUTDOWN immediate;
 SQL>startup;

 如果按上面的做法做,National charset的区域设置就没有问题。
   注意:以上步骤中的SQL命令需要一步一步的执行,因为每一步都有执行的延迟,而下一步依赖上一步的操作,所以不能批量执行。(开始一下子全部粘贴到命令行执行,靠后的语句都报错!)

2、修改client端字符集
   手动修改系统注册表即可,
   windows为HKLM\SOFTWARE\ORACLE\KEY_OraClient10g_homexx\NLS_LANG的值为YourCharset。

3、还需要注意的是字符集之间的超子集关系,否则盲目的改也不起作用,只是乱码字符变了。

更详细请参考:http://oracle.chinaitlab.com/induction/799785_2.html