SQL> select * from nls_database_parameters;
PARAMETER VALUE
------------------------------ --------------------------------------------------------------------------------
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CHARACTERSET ZHS16GBK
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_SORT BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
NLS_NCHAR_CHARACTERSET AL16UTF16
NLS_RDBMS_VERSION 11.2.0.1.0
它的格式如下: NLS_LANG = language_territory.charset
它有三个组成部分(语言、地域和字符集),每个成分控制了NLS子集的特性。
其中:
Language: 指定服务器消息的语言, 影响提示信息是中文还是英文
Territory: 指定服务器的日期和数字格式,
Charset: 指定字符集。
如:AMERICAN _ AMERICA. ZHS16GBK
从NLS_LANG的组成我们可以看出,真正影响数据库字符集的其实是第三部分。
数据库字符集(oracle服务器端字符集)
数据库字符集在创建数据库时指定,在创建后通常不能更改。在创建数据库时,可以指定字符集(CHARACTER SET)和国家字符集(NATIONAL CHARACTER SET)。
字符集
(1)用来存储CHAR, VARCHAR2, CLOB, LONG等类型数据
(2)用来标示诸如表名、列名以及PL/SQL变量等
(3)用来存储SQL和PL/SQL程序单元等
国家字符集:
(1)用以存储NCHAR, NVARCHAR2, NCLOB等类型数据
(2)国家字符集实质上是为oracle选择的附加字符集,主要作用是为了增强oracle的字符处理能力,因为NCHAR数据类型可以提供对亚洲使用定长多字节编码的支持,而数据库字符集则不能。国家字符集在oracle9i中进行了重新定义,只能在unicode编码中的AF16UTF16和UTF8中选择,默认值是AF16UTF16
当一种字符集(字符集A)的编码数值包含所有另一种字符集(字符集B)的编码数值,并且两种字符集相同编码数值代表相同的字符时,则字符集A是字符集B的超级,或称字符集B是字符集A的子集。
Oracle8i和oracle9i官方文档资料中备有子集-超级对照表(subset-superset pairs),例如:WE8ISO8859P1是WE8MSWIN1252的子集。由于US7ASCII是最早的Oracle数据库编码格式,因此有许多字符集是US7ASCII的超集,例如WE8ISO8859P1、ZHS16CGB231280、ZHS16GBK都是US7ASCII的超集。
查询字符集参数
可以查询以下数据字典或视图查看字符集设置情况
nls_database_parameters
props$
v$nls_parameters
查询结果中NLS_CHARACTERSET表示字符集,NLS_NCHAR_CHARACTERSET表示国家字符集
数据库端字符集的修改(不推荐使用)
1. 关闭数据库
SQL>SHUTDOWN IMMEDIATE
2. 启动到Mount
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 AL16UTF16;
--如果是从子集到父集,需要使用INTERNAL_USE参数,跳过超子集检测
SQL>ALTER DATABASE CHARACTER SET INTERNAL_USE AL32UTF8;
SQL>ALTER DATABASE NATIONAL CHARACTER SET INTERNAL_USE AL16UTF16;
SQL>SHUTDOWN IMMEDIATE;
SQL>STARTUP
注意:如果没有大对象,在使用过程中进行语言转换没有什么影响,(切记设定的字符集必须是ORACLE支持,不然不能start) 按上面的做法就可以。
若出现‘ORA-12717: Cannot ALTER DATABASE NATIONAL CHARACTER SET when NCLOB data exists’ 这样的提示信息,
要解决这个问题有两种方法
1. 利用INTERNAL_USE 关键字修改区域设置,
2. 利用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_USEUTF8;
SQL>SHUTDOWN immediate;
SQL>startup;
如果按上面的做法做,National charset的区域设置就没有问题
修改dmp文件字符集
上文说过,dmp文件的第2第3字节记录了字符集信息,因此直接修改dmp文件的第2第3字节的内容就可以‘骗’过oracle的检查。这样做理论上也仅是从子集到超集可以修改,但很多情况下在没有子集和超集关系的情况下也可以修改,我们常用的一些字符集,如US7ASCII,WE8ISO8859P1,ZHS16CGB231280,ZHS16GBK基本都可以改。因为改的只是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即可。
如果dmp文件很大,用ue无法打开,就需要用程序的方法了。
数据库字符集与客户端NLS_LANG设置不同引起的乱码:
例如:对于一个需要存储简体文信息的数据库来说,它的字符集设置和客户端NLS_LANG设置一般可以使用ZHS16GBK编码。但是如果数据库字符集选用了UTF8的话,也是可以的,因为ZHS16GBK编码属于UTF8的子集。ORACLE在数据库与客户端进行数据交换时自动进行编码的转换,在数据库中实际存储的也是UTF8编码的数据。此时其它数据库和此数据库也可以正常的进行数据交换,因为ORACLE会自动进行数据的转换。在实际使用中,遇到过繁体XP的字符集ZHT16MSWIN950转换成AL32UTF8字符集时,一些特殊的字符和个别冷僻的汉字会变成乱码。后来证实是XP需要安装一个字库补丁软件,最后顺利解决此问题。
客户端NLS_LANG与本地化环境不同引起的乱码:
一般情况下,客户端NLS_LANG与本地化环境采用了不同的字符集会出现乱码,除非本地化环境的字符集是客户端NLS_LANG设置字符集的子集。如果把客户端NLS_LANG设置为UTF8就属于这种情况,由于目前还没有可以直接使用UNICODE字符集的操作系统,因此客户本地化环境使用的字符集只能是某种语言支持的字符集,它属于UTF8的子集。下面我们就着重讨论这种情况。
虽然目前WINDOWS的内核是支持UNICODE的,但是WINDOWS并不支持直接显示UNICODE编码的字符,而且它并不知道目前的字符采用了何种字符集,所以默认情况下,它使用缺省的代码页来解释字符。因此,对于其它类型的编码,需要先进行转换,变成系统目前的缺省代码页支持的字符集才能正常使用。
WINDOWS中的缺省代码页是由控制面板设置中的语言及区域的选择所决定的,属于客户本地化的环境设置。简体中文WINDOWS的字符编码就是GBK,它的缺省代码页是936。对于其它非WINDOWS的操作系统,我们可以把它们目前缺省使用的字符集作为用户的本地化环境设置。另外,我们使用的大部分工具,如写字板,SQL*PLUS等,它们没有提供编码转换功能,因此在客户端直接输入或查询数据往往都会遇到乱码的问题,必须由应用程序或一些工具去做编码的转换,才能保证正常的使用。
客户端字符集定义了客户端字符数据的编码方式,任何发自或发往客户端的字符数据均使用客户端定义的字符集编码,客户端可以看作是能与数据库直接连接的各种应用,例如sqlplus,exp/imp等。客户端字符集是通过设置NLS_LANG参数来设定的。
NLS_LANG参数格式
NLS_LANG=<language>_<territory>.<client character set>
Language: 显示oracle消息,校验,日期命名
Territory:指定默认日期、数字、货币等格式
Client character set:指定客户端将使用的字符集
例如:NLS_LANG=AMERICAN_AMERICA.US7ASCII
AMERICAN是语言,AMERICA是地区,US7ASCII是客户端字符集
客户端字符集设置方法
1)UNIX环境
查看unix环境字符集:
/opt/oracle>env|grep NLS_LANG
NLS_LANG=AMERICAN_CHINA.ZHS16GBK
设置客户端字符集:
$NLS_LANG=“simplified chinese”_china.zhs16gbk
$export NLS_LANG
编辑oracle用户的profile文件
2)Windows环境
查看客户端字符集
E:\>echo %NLS_LANG%
AMERICAN_AMERICA.ZHS16GBK
编辑注册表
Regedit.exe ---》 HKEY_LOCAL_MACHINE ---》SOFTWARE ---》 ORACLE--》HOME
或者在窗口设置:
set nls_lang=AMERICAN_AMERICA.ZHS16GBK
查看数据库当前字符集参数设置
SELECT * FROM v$nls_parameters;
查看数据库可用字符集参数设置
SELECT * FROM v$nls_valid_values;
(查看session字符集
select * from V$NLS_SESSION_PARAMETERS
select *from nls_database_parameters
select *From v$nls_parameters
客户端 NLS_LANG 的设置方法
Windows:
# 常用中文字符集
set NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
# 常用unicode字符集
set NLS_LANG=american_america.AL32UTF8
可以通过修改注册表键值永久设置
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOMExx\NLS_LANG
Unix:
# 常用unicode字符集
export NLS_LANG=american_america.AL32UTF8
# 常用中文字符集
export
可以编辑 bash_profile 文件进行永久设置
vi .bash_profile
export NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK"
or export NLS_LANG="Simplified Chinese_china".ZHS16GBK
s# 使 bash_profile 设置生效
source .bash_profile