select * from nls_instance_parameters where parameter =‘NLS_TERRITORY‘ or parameter =‘NLS_LANGUAGE‘;
select * from nls_instance_parameters where parameter =‘NLS_TERRITORY‘ or parameter =‘NLS_LANGUAGE‘;
select * from nls_database_parameters where parameter =‘NLS_TERRITORY‘or parameter =‘NLS_LANGUAGE‘;
export NLS_LANG=.zhs16gbk 或者 (LANG=zh_CN.zhs16gbk)不适用
RedHat linux AS4.0安装了oracle10g,同时创建数据库实例sc,后来又用dbca建立一个数据库实例st,发现在oracle系统用户下用sqlplus连接st实例时出现乱码,应该是中文无法显示造成的,但连接sc实例时无乱码,显示英文。上网搜集了一下资料,修改了oracle系统用户的环境变量在.bash_profile中新增了以下内容解决:
export NLS_LANG=AMERICAN_AMERICA.UTF8
export.UTF-8
分析原因:
引用网上帖子:
oracle字符集问题一般可以分为三类: 数据库字符集, sqlplus的字符集(客户端字符集), 终端程序的字符集(非oracle的)。
1、数据库字符集。
数据库字符集是所有字符问题的核心,只有数据库本身的字符集正确了,客户端的字符集才可能正确。这里只的客户端包括sqlplus以及我们自己读数据库的应用程序。
在定位问题时,我们需要先看看数据库当前是什么字符集。
1)查询数据库字符集
select * from nls_database_parameters
其中 nls_language表示了显示方式, 就是sqlplus的程序的显示字体,有SIMPLIFIED CHINESE,American america
其中 nls_characterset是字符集设定, 常用的一些字符集有UTF8,US7ASCII,WE8ISO8859P1,ZHS16CGB231280,ZHS16GBK, AL32UTF8
2)修改数据库字符集
当发现数据库字符集不正确时,如我们期望时GBK的,而数据库当前是其他的,从而引起中文乱码。这时我们需要修改数据库字符集。步骤如下:
$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 ZHS16GBK;
SQL>ALTER DATABASE national CHARACTER SET ZHS16GBK;
SQL>SHUTDOWN IMMEDIATE;
SQL>STARTUP
2 客户端字符集
如果服务器端的字符集是正确的,而在客户端下,如sqlplus仍然不能正确显示中文,这一般是由于服务器端的字符集设定与客户端的字符集设定不同造成的。只要将两者修改一致就可以解决问题。
1)查询客户端字符集
select * from nls_instance_parameters
客户端字符集环境select * from nls_instance_parameters,其来源于v$parameter,
表示客户端的字符集的设置,可能是参数文件,环境变量或者是注册表
select userenv(‘language‘) from dual;
会话字符集环境 select * from nls_session_parameters,其来源于v$nls_parameters,表示会话自己的设置,可能是会话的环境变量或者是alter session完成,如果会话没有特殊的设置,将与nls_instance_parameters一致。
客户端的字符集要求与服务器一致,才能正确显示数据库的非Ascii字符。如果多个设置存在的时候,alter session>环境变量>注册表>参数文件
字符集要求一致,但是语言设置却可以不同,语言设置建议用英文。如字符集是zhs16gbk,则nls_lang可以是American_America.zhs16gbk。 或者.zhs16gbk。注意zhs16gbk前面那个点是必须的哦!!
2) 修改客户端字符集
oracle 的sqlplus会去读取OS中环境变量下的nls_lang信息(关键在这里,通过以上命令查看
select * from nls_database_parameters 显示
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
select * from nls_instance_parameters 显示
NLS_LANGUAGE SIMPLIFIED CHINESE
NLS_TERRITORY CHINA
NLS_SORT
NLS_DATE_LANGUAGE
NLS_DATE_FORMAT
NLS_CURRENCY
select * from nls_session_parameters 显示
NLS_LANGUAGE SIMPLIFIED CHINESE
NLS_TERRITORY CHINA
NLS_CURRENCY RMB
也就是说会话字符集与终端字符集一致,而与数据库字符集设置不一致。
另一个数据库实例sc
数据库字符集
select * from nls_database_parameters 显示
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
select * from nls_instance_parameters 显示
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_SORT
NLS_DATE_LANGUAGE
NLS_DATE_FORMAT
NLS_CURRENCY
在linux下
select * from nls_session_parameters 显示
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
用TOD 在windows下显示
NLS_LANGUAGE SIMPLIFIED CHINESE
NLS_TERRITORY CHINA
NLS_CURRENCY RMB
这个我还搞不明白为什么windows与linux会话字符集为什么不一样。
更搞不明白的是为什么两个数据库实例用同一个系统用户查询的,也就是说环境变量是一样的,但查询结果终端字符集为什么会不一样?初步分析(当然不一定对,欢迎指正)是两个数据库实例的参数文件不一致引起的,因为alter session>环境变量>注册表>参数文件,也就是说因为环境变量没有设置,但sc与st数据库实例参数文件不同,但是参数文件在什么地方设还不清楚,有高手欢迎指点!
但基本上问题锁定是因为终端字符集与数据库字符集不一致引起,在用户的环境变量中增加
export NLS_LANG=AMERICAN_AMERICA.UTF8
export.UTF-8
--alter database character set utf-8
问题解决
再次查看客户端字符集
select * from nls_instance_parameters 还是显示
NLS_LANGUAGE SIMPLIFIED CHINESE
NLS_TERRITORY CHINA
NLS_SORT
NLS_DATE_LANGUAGE
NLS_DATE_FORMAT
NLS_CURRENCY
但
select * from nls_session_parameters 显示
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
看来只要本次会话字符集正确就没问题了,经过验证确实如此,用
alter session set NLS_LANGUAGE=‘AMERICAN’后本次会话也不会出现乱码的。
)
NSL_LANG包括三个部分(语言_地区.字符集)就是V$NLS_PARAMETERS表中的NLS_LANGUAGE,NLS_TERRITORY,NLS_CHARACTERSET
例如可以在cmd中键入
set nls_lang="Simplified chinese_china.utf8"
set nls_lang="american_america.us7ascii"
set nls_lang="american_america.zhs16gbk"
set nls_lang="Simplified chinese_china.zhs16gbk"
set nls_lang=".utf8"
set nls_lang=".zhs16gbk"
set nls_lang=".us7ascii"
unix下类似, 不过nls_lang要大写NLS_LANG, 在.profile或这.bash_profile(根据你用的shell)里更改NLS_LANG可以长久保持环境变量值.
3、终端字符集
如果数据库字符集和sqlplus的字符集一致, 还是不能正确显示了, 那很可能就是你的终端应用程序的字符集不支持了. 例如你用bash登陆sqlplus, 如果你的bash是个小字符集, 那么就不能正常显示了.linux修改bash的字符集, 可以先键入locale, 看有哪些环境变量, 再用export设置.
4.EXP/IMP 与 字符集
4.1 EXP/IMP Export 和 Import 是一对读写Oracle数据的工具。Export 将 Oracle 数据库中的数据输出到操作系统文件中, Import 把这些文件中的数据读到Oracle 数据库中,由于使用exp/imp进行数据迁移时,数据从源数据库到目标数据库的过程中有四个环节涉及到字符集,如果这四个环节的字符集不一致,将会发生字符集转换。 EXP ____________ _________________ _____________ |imp导入文件|<-|环境变量NLS_LANG|<-|数据库字符集| ------------ ----------------- -------------IMP ____________ _________________ _____________ |imp导入文件|->|环境变量NLS_LANG|->|数据库字符集| ------------ ----------------- ------------- 四个字符集是 (1)源数据库字符集 (2)Export过程中用户会话字符集(通过NLS_LANG设定) (3)Import过程中用户会话字符集(通过NLS_LANG设定) (4)目标数据库字符集 4.2导出的转换过程 在Export过程中,如果源数据库字符集与Export用户会话字符集不一致,会发生字符集转换,并在导出文件的头部几个字节中存储Export用户会话字符集的ID号。在这个转换过程中可能发生数据的丢失。例:如果源数据库使用ZHS16GBK,而Export用户会话字符集使用US7ASCII,由于ZHS16GBK是16位字符集,而US7ASCII是7位字符集,这个转换过程中,中文字符在US7ASCII中不能够找到对等的字符,所以所有中文字符都会丢失而变成“?? ”形式,这样转换后生成的Dmp文件已经发生了数据丢失。因此如果想正确导出源数据库数据,则Export过程中用户会话字符集应等于源数据库字符集或是源数据库字符集的超集 43导入的转换过程 (1)确定导出数据库字符集环境 通过读取导出文件头,可以获得导出文件的字符集设置 (2)确定导入session的字符集,即导入Session使用的NLS_LANG环境变量 (3)IMP读取导出文件 读取导出文件字符集ID,和导入进程的NLS_LANG进行比较 (4)如果导出文件字符集和导入Session字符集相同,那么在这一步骤内就不需要转换, 如果不同,就需要把数据转换为导入Session使用的字符集。可以看出,导入数据到数据库过程中发生两次字符集转换 第一次:导入文件字符集与导入Session使用的字符集之间的转换,如果这个转换过程不能正确完成,Import向目标数据库的导入过程也就不能完成。 第二次:导入Session字符集与数据库字符集之间的转换。