Oracle-OCP学习笔记:字符集

linux环境下字符集:

[root@single ~]# locale

LANG=en_US.UTF-8

LC_CTYPE="en_US.UTF-8"

#export NLS_LANG=american_america.zhs16gbk

 

windows环境下字符集:

C:\Users\Martin>chcp

活动代码页: 936

C:>set NLS_LANG=american_america.zhs16gbk

 

 

字符集分类:

       操作系统字符集

       Oracle软件字符集

       Sql developer软件带字符集,如果软件没有字符集,则使用操作系统字符集

 

SYS AS SYSDBA@ORCL>desc t2;

 Name                                       Null?   Type

ID                                           NUMBER(38)

 NAME                                           VARCHAR2(20)

ID例是数字列,不需要使用字符集

NAME列是VARCHAR2表,需要使用字符集来转换。

 

 

字符集的作用和含义:

    字符编码

    使用场合

       数据库字符集,以下类型要使用字符集。

1. 用来存储CHAR,VARCHAR2,CLOB,LONG等类型数据

2. 用来标示诸如表名,列名以及PL/SQL变量等

3. 用来存储SQL和PL/SQL程序单元等

 

国家字符集:

用来存储NCHAR,NVARCHAR2,NCLOB等类型数据,如果没有这些类型的数据,则不需要使用国家字符集。

 

SYS ASSYSDBA@ORCL>desc t3;

 Name                                       Null?   Type

-----------------------------------------------------------------------------------

 ID                                          NUMBER

 NAME                                       NVARCHAR2(20)

 

 

客户端OS字符集,NLS_LANG设置,服务端OS字符集,ORACLE数据库字符集

       字符集之间的关系

       正确设置字符集

 

字符集出现问题以后的判断流程

       存储的是错误的字符集

       存储是的正确的字符集

 

Locale  locale –a,chcp

 

 

字符集其实就是“字符”和“编码”的一张对照表

 

字符集原理:

字符集就是一个表,有两列,

左边的列是要存储的字符,比如中文字符”阮胜昌”

右边的列是一个编码,也就是计算机里面存储的数字。因为计算机里面只能存储数字,不能存储字符。

所以字符集是我们所能看到的字符与字符对应的编码的对应表。

 

 

字符集命名:

ORACLE的字符集命令遵循以下命名规则:

<Language><bit size><encoding>

即:<语言><比特位数><编码>

比如:ZHS16GBK表示采用GBK编码格式,16位(两个字节),简体中文字符集

 

US7ASCII  #只能存储美国人使用的字符,26个字母,数字,运算符号(+-*/),总量不超过128个字符

 

 

ZHS16CGB231280  #中文字符集,是国标,比较老了

ZHS16GBK   #最新的中文字符集,是字符集Zhs16CGB231280的超集,不是严格超集

 

 

AF16UTF16#国家字符集

 

unicode字符集:

AL32UTF8   #最新的UTF8字符集(国际型企业,即有中文字符,也有其它国家的字符)

UTF8       #比较老,字符集不全面

注:实际生产环境,如果确定数据库只是中国人用(只有中英文相关字符)的话,就采用ZHS16GBK..

 

 

数据库安装过程中,会选择确认下面两个字符集:

1.数据库字符集:数据库需要存储多国语言选择AL32UTF8,只有中英文选择ZHS16GBK

2.国家字符集 一般都选用AL16UTF16

 

 

 

NLS_LANG=<language>_<territory>.<clientcharacter set>

       Language:显示oracle消息,校验,日期命名,是用中文显示还是英文显示

       Territory:指定默认日期,数字,货币等格式

       Clientcharacter set:指定客户端将使用的字符集

       例如:NLS_LANG=AMERICAN_AMERICA.US7ASCII

       AMERICAN:是语言,AMERICA是地区,US7ASCII是客户端字符集

 

Oracle提供若干NLS参数定制数据库和用户以适应本地格式,例如有NLS_LANGUAGE,NLS_DATE_FORMAT,NLS_CALENDER等,可以通过查询以下数字字典或v$视图查看。

NLS_DATABASE_PARAMETERS –显示数据库当前NLS参数取值,包括数据库字符集取值

NLS_SESSION_PARAMETERS   -显示由NLS_LANG设置的参数,或经过alter session改变后的参数值(不包括由NLS_LANG设置的客户端字符集)

NLS_INSTANCE_PARAMETE    -显示由参数文件init<SID>.ora定义的参数

V$NLS_PARAMETERS         -显示数据库当前NLS参数取值。

 

查看数据库字符集:用得多

SYS AS SYSDBA@ORCL>select * fromnls_database_parameters where PARAMETER='NLS_CHARACTERSET';

PARAMETER           VALUE

NLS_CHARACTERSET   AL32UTF8

查看国家字符集:用得少,做为数据库字符集的补充

SYS AS SYSDBA@ORCL>select * fromnls_database_parameters where PARAMETER='NLS_NCHAR_CHARACTERSET';

PARAMETER                   VALUE

NLS_NCHAR_CHARACTERSET      UTF8

 

查看当前session使用的字符集:

SYS AS SYSDBA@ORCL>select * from nls_session_parameters;

 

SYS AS SYSDBA@ORCL>select userenv('language') fromdual;

 

USERENV('LANGUAGE')

-------------------------------------------------

SIMPLIFIED CHINESE_CHINA.AL32UTF8

 

SYS AS SYSDBA@ORCL>select nls_charset_name(to_number('0354','xxxx'))from dual;

 

NLS_CHARSET_NAME(TO_NUMBER('0354','XXXX'))

----------------------------------------------

ZHS16GBK

 

SYS AS SYSDBA@ORCL>! echo $NLS_LANG

SIMPLIFIED CHINESE_CHINA.UTF8

 

SYS AS SYSDBA@ORCL>select to_char(nls_charset_id('ZHS16GBK'),'xxxx')from dual;

 

TO_CHAR(NLS_CHARSET_ID('ZHS16GBK'),'XXXX')

------------------------------------------------------------------------------------------------------------------------------------------------------

  354

 

查看系统支持的字符集:

SYS AS SYSDBA@ORCL>select * from V$NLS_VALID_VALUES;

 

sql*plus客户端设置原则:与所在操作系统字符集一致):

sqlplus 没有字符集,他引用操作系统字符集

sqldeveloper 这个软件有字符集,所有不用操作系统字符集

oracle有字符集,所有oracle不用操作系统字符集

总结:如果oracle client如果有字符集,以软件字符集为主,不会用操作系统的字符集,所有字符集的转换都在oracle内部完成的。

 

客户端字符集配置:(通过配置客户端字符集,oracle就知道客户端用什么字符集编码。)

windows:一般都是gbk,即chcp结果为936

c:>set NLS_LANG=american_america.zhs16gbk

语言和地区为中文中国的话,set NLS_LANG=simplifiedchinese_china.zhs16gbk

 

linux:一般为utf-8,即echo $LANG 结果为en_US.UTF-8 或zh_CN.UTF-8

#export NLS_LANG=american_america.utf8

 

以下是错误的字符集配置:

原则:客户端的NLS_LANG配置的字符集要与客户端软件或客户端操作系统的字符集要一样

ORACLE不管是存数据还是取数据,都要向客户端询问,对方传过来的编码是通过什么字符集转换的。

       如果数据库字符集与客户端的字符集一样,ORACLE不会发生字符集转换,

       如果数据库字符集与客户端的字符集不一样,ORACLE会发生这符集转换。

 

以下图的客户端字符集与NLS_LANG字符集不一样,这是错误的,正常的配置是NLS_LANG字符集要配置成与客户端服务器或客户端软件的字符集一样。


上图错误的原因:

       客户端在varchar2等类型的列上存一个字符,这时在客户端会将字符转换成编码A4。这时将这个A4发送到ORACLE服务端,这时ORACLE就会问,这个A4编码中用什么字符集编码的,因为这时客户端的NLS_LANG字符集为WE8MSWIN1252,所以oracle就认为客户端的字符集为WE8MSWIN1252,而不是实际的WE8ISO8859P15。这时oracle看了一下数据库的字符集是AL32UTF8,与客户端的字符集WE8MSWIN1252,所有ORACLE会先将A4这个编码用WE8MSWIN1252字符集转换成A4对应的字符。再将字符通过AL32UTF8转换成编码C2A4ORACLE就直接存这个转换好的编码C2A4

       当客户端读取数据库的字符时,ORACLE返回以AL32UTF8字符集对应的编码C2A4,ORACLE查看到NLS_LANG的字符集为WE8MSWIN1252,与数据库的字符集不一样。所以ORACLE会将C2A4先通过AL32UTF8转换为字符,再用这个字符通过WE8MSWIN1252转换成编码。这时客户端看到的就是这个编码,但这时通过WE8ISO8859P15字符集解析这个编码时得不到原来的字符,这时的字符就产生的乱码。

下图的NLS_LANG字符集与数据库的字符集一样,与客户端的字符集不一样。



上图错误的原因:

       客户端将字符编码后得到A4编码,这时客户端NLS_LANG配置为UTF8,而数据库的字符集也是UTF8,所以当将这个编码传到数据库时,ORACLE看到客户端的NLS_LANG的字符集与数据库的字符集一样,所有oracle不会转换,而是直接将编码A4存入数据库。

 

 

测试:

客户端Linux,系统字符集为zh_CN.UTF-8

正确设置:

#export LANG=zh_CN.UTF-8

#export NLS_LANG=american_america.utf8

[oracle@oracle ~]$ echo $NLS_LANG

american_america.utf8

[oracle@oracle ~]$ echo $LANG

zh_CN.UTF-8

 

SYS AS SYSDBA@ORCL>select * from t3;

    ID NAME

---------- --------------------

         1 阮胜昌

 

commit;

查看字符对应的编码:这个编码就是oracle存储下来的。

SYS AS SYSDBA@ORCL>select id,name,dump(name,1016) fromt3;

 

    ID NAME

---------- --------------------

DUMP(NAME,1016)

------------------------------------------------------------------------------------------------------------------------------------------------------

         1 阮胜昌

Typ=1 Len=9 CharacterSet=UTF8: e9,98,ae,e8,83,9c,e6,98,8c  #以16进制显示

 

select id,name,dump(name,1010) from t3;  #以10进制显示

Typ=1 Len=9 CharacterSet=UTF8:233,152,174,232,131,156,230,152,140

 

select id,name,dump(name,1008) from t3; #以8进制显示

Typ=1 Len=9 CharacterSet=UTF8:351,230,256,350,203,234,346,230,214

 

错误配置1:

[oracle@oracle ~]$ echo $LANG

en_US.UTF-8

[oracle@oracle ~]$ echo $NLS_LANG

SIMPLIFIED CHINESE_CHINA.UTF8

SYS AS SYSDBA@ORCL>select id,name from t3;

    ID NAME

---------- --------------------

         1 莜?

错误配置2:

#export NLS_LANG=american_america.zhs16gbk

select dump('靖宇',1016) from dual;

insert into t2 values (2,'靖宇');

commit;

 

注意:字符集设置错误导致库中存储的就是错误的编码,这个几乎是不可逆的`一定要慎重仔细设置好字符集。

 

查看字符:阮胜昌字符正确的编码:

SYS AS SYSDBA@ORCL>select dump('阮胜昌',1016) from dual;

DUMP('阮胜昌',1016)

Typ=96 Len=9 CharacterSet=AL32UTF8:e9,98,ae,e8,83,9c,e6,98,8c

 

insert into t2 values (2,'阮胜昌');

commit;

 

 

 

服务器上oracle字符集

如何确定当前字符集设定,何时可以更改字符集。

SYS AS SYSDBA@ORCL>select userenv('language') fromdual;

USERENV('LANGUAGE')

AMERICAN_AMERICA.AL32UTF8

 

查看系统的字符集:

select * from v$nls_parameters;

 

 

了解超集,严格超集的概念,确定是否可以更改字符集。Oracle不建议后期更改数据库字符集!

服务器操作系统字符集(暂时忽略)

 

ps:

1.因为sql*plus 本身没有字符集,依赖于所在操作系统的字符集,而在远端linux上的oracle也是无法直接访问到windows上的字符集,所以依靠sql*plus的NLS_LANG设置来辨别。

2.因为oracle软件本身有字符集,当软件有自己的字符集时,就不用操作系统的字符集,所以服务器操作系统字符集的因素可以暂时忽略。

 


分割线
感谢打赏
江西数库信息技术有限公司
YWSOS.COM 平台代运维解决方案
 评论
 发表评论
姓   名:

Powered by AKCMS