说一下我的最初需求:创建数据库时,设置的编码是ZHS16GBK,NLS_LANG配置的也是ZHS16GBK。写了一个sql脚本,该脚本在一个web项目里,整个web项目编码格式都为UTF8,初始化数据库想使用java调用oracle命令来执行该脚本,但是用oralcle的命令执行该脚本时,存到数据库中的中文是乱码的。
分析原因:
如果想要搞清楚Oracle的字符系统,需要紧紧地抓住三个因素:
一.“客户终端字符集”
二.“NLS_LANG”环境变量
三.“数据库字符集”
数据库字符集直接查看方法:select * fromnls_database_parameters;
或者 select * fromv$nls_parameters;找到:
NLS_LANGUAGE
NLS_TERRITORY
NLS_CHARACTERSET
环境变量nls_lang便是由这三部分组成
NLS_LANG = language_territory.charset
比如:NLS_LANG = SIMPLIFIEDCHINESE_CHINA.UTF8
客户终端字符集查看方法:
32位在:HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432NODE\ORACLE\KEY_OraDb11g_home1\NLS_LANG
64位在:HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraDb11g_home1\NLS_LANG
下面我们通过实际操作来验证:将ORACLE11g数据库字符集从ZHS16GBK转为UTF8(或AL32UTF8也可以)
步骤一:执行以下命令
sqlplus "/as sysdba"
conn /as sysdba;
shutdown immediate;
startup mount;
ALTER SYSTEM ENABLE RESTRICTED SESSION;
ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
ALTER SYSTEM SET AQ_TM_PROCESSES=0;
alter database open;
alter database character set UTF8;
shutdown immediate;
startup;
步骤二:执行完毕后,设置客户端字符集:
32位在:HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432NODE\ORACLE\KEY_OraDb11g_home1\NLS_LANG
64位在:HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraDb11g_home1\NLS_LANG
按照上述路径找到后设置NLS_LANG的值为SIMPLIFIED CHINESE_CHINA.UTF8
步骤三:最后再设置环境变量NLS_LANG的值为SIMPLIFIED CHINESE_CHINA.UTF8重启电脑即可,然后执行utf8编码的sql脚本不再出现乱码。本人电脑win764位,ORACLE11g64位亲测可行。
PS:虽然用java执行sql脚本不乱码了,但是,把环境变量NLS_LANG的值修改后,又会导致sqlplus中文提示乱码和plsql日期显示乱码,因为像sqlplus和cmd这种窗口命令并没有自己的字符集,它使用系统字符集,当NLS_LANG设置的字符集和系统不兼容时就会导致它的中文乱码。真的找不到好的解决办法,对于不用sqlplus和plsql的童鞋来说就不是什么问题了。
在网上搜到一个折中的办法就是把NLS_LANG的值设置为:AMERICAN_AMERICA.UTF8,那么sqlplus的提示不使用中文,使用英文,plsql的日期类型字段时间也显示正常。
总结:
如果“NLS_LANG”等于“数据库字符集”时,不需要进行任何转换,直接把字符插入数据库
如果“NLS_LANG”不等于“数据库字符集”,则需要进行转换,乱码的根源就在这里。
如果“NLS_LANG”编码跟sql脚本一致,则插入数据库的数据基本不会乱码,但是有可能会导致sqlplus中文提示乱码。
如果“NLS_LANG”编码跟sql脚本不一致,和系统一直,则插入数据库的数据可能会乱码,sqlplus中文提示不乱码。
开发时注意:
1、如果有可能,尽量保证客户端编码(Windows 的cmd工具可以使用chcp命令来查看系统字符集)、NLS_LANG参数和数据库字符集这三个内容一致,这样设置,无论是从性能上,还是从防止编码转换上都是最佳的;
2、如果目的是支持中文,数据库Server端的字符集应该尽量选择ZHS16GBK或UTF8字符集,这样可以减少因不当的“转码”导致的字符乱码故障;
3、(推荐)可已将NLS_LANG参数与操作终端字符编码一致,这样可以保证数据库能正确获得应用终端使用的编码,这时会发生“编码转换”,但是,这样就可以保证正确转码,可以防止错误的编码存入数据库;
4、(不推荐)也可以将NLS_LANG参数与数据库服务器端的编码一致,这样,客户端无论是发送到服务器端还是从服务器接收数据都不会“转码”,这样能保证客户端对字符的显示效果,但是,一定要小心,这时数据库服务器上存放的字符编码很可能是错误的。
5、PL/SQL Developer工具在UTF8字符集下貌似可以保证数据效果,但是使用Toad工具时貌似不太稳定”。