起因: 在处理某次问题时需要使用insert语句在某张表中插入大概5000条数据(oracle数据库)。
经过: 首先使用plsql执行sql文件,但是发现执行后笔记本plsql长时间无响应卡死,后来使用DB服务器sqlplus执行sql文件,将sql文件上传至服务器进行测试,测试后发现无异常,执行中shell并未发现异常。
结果:测试完成后在另一个服务器上执行却出现了中文乱码导致所插入记录无法读取。
问题分析:
问题的原因是数据库服务器对应用户 ~/.bash_profile文件默认字符集与oracle默认字符集不同,sqlplus使用了linux用户默认的字符集。(oracle使用 AL32UTF8 ;linuxDB服务器使用utf-8)
- 如果软件有字符集,就不会使用操作系统的字符集;
- 如果没有字符集(比如SQL/PLUS就没有字符集),那么在输入和显示中文时就调用操作系统的字符集来进行编码。Oracle数据库通过查看nls_language来获取操作系统使用的字符集,如果俩字符集是一致的,那么就会直接将编码存入Oracle数据库;
- 如果不一致,Oracle数据库首先会用nls_lang所表明的字符集将编码转化成字符,然后用Oracle数据库自己的字符集将字符转化成编码存入数据库。
相关的字符集一共有三种:
- a.操作系统字符集
- b.Oracle数据库字符集
- c.软件字符集
如何避免:NLS_LANG一定要设置成与操作系统字符集一致才不会出现中文乱码或者显示的问题。 使用sqlplus执行sql时要查询Oracle数据库字符集与操作系统字符集,否则会导致中文乱码。
- 使用export NLS_LANG=american_america.AL32UTF8临时改变字符集(仅当次有效)
- 使用SQLplus导入(要确认sqlplus字符集一致,数据量大卡死可以使用sqlplus命令行窗口,执行方法sql>@D:/insert.sql)
查询方法:
服务端字符集
select * from v$nls_parameters where parameter='NLS_CHARACTERSET';
客户端字符集
linux : vi ~/.bashrc 查看 export LANG=zh_cn.utf8 export LC_ALL=zh_cn.utf8 字符集(使用export临时修改)
vi .bash_profile
NLS_LANG="Simplified Chinese_china".ZHS16GBK export NLS_LANG
# 使 bash_profile 设置生效
source .bash_profile
Windows: echo %NLS_LANG%
# 设置字符集
set NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
部分内容参考 行者摩罗
链接 Sqlplus连接Oracle出现中文乱码问题以及字符集的选择