暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle字符集问题

oracleEDU 2017-08-15
805

目录

一、什么是字符集

        1.字符编码方案

            i.单字节编码

            ii.多字节编码

            iii.unicode编码

        2.字符集超级

二、如何使用字符集

        1.oracle服务器端字符集

        2.客户端字符集

        3.乱码产生与解决

什么是字符集

字符集

    实质就是按照一定的字符编码方案,对一组特定的符号,分别赋予不同数值编码的集合。Oracle数据库最早支持的编码方案是US7ASCII。

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

 <Language><bit size><encoding>

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

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

01

字符编码方案

单字节编码

    (1)单字节7位字符集,可以定义128个字符,最常用的字符集为US7ASCII

    (2)单字节8位字符集,可以定义256个字符,适合于欧洲大部分国家

例如:WE8ISO8859P1(西欧、8位、ISO标准8859P1编码)

多字节编码

    (1)变长多字节编码

    某些字符用一个字节表示,其它字符用两个或多个字符表示,变长多字节编码常用于对亚洲语言的支持,例如日语、汉语、印地语等

    例如:AL32UTF8(其中AL代表ALL,指适用于所有语言)、zhs16cgb231280

    (2)定长多字节编码

    每一个字符都使用固定长度字节的编码方案,目前oracle唯一支持的定长多字节编码是AF16UTF16,也是仅用于国家字符集

unicode编码

    Unicode是一个涵盖了目前全世界使用的所有已知字符的单一编码方案,也就是说Unicode为每一个字符提供唯一的编码 

    

    UTF-8是unicode的8位编码方式,是一种变长多字节编码,

它是一种宽度可变的编码,也是严格的ASCII的超集,也就意味着7位ascii中的每个字符在al32utf8中都可以具有相同的码点值。

一个unicode字符可以是1,2,3,4个字节。

欧洲用1或2个字节表示

大多数亚洲使用3个字节表示

增补使用4个字节表示

AL32UTF16 unicode的16位编码

一个unicode字符可以是2到4字节, 欧洲和大多数亚洲使用2字节表示,增补字符使用4个字节表表示,windows主要使用unicode编码

02

字符集超级

当一种字符集(字符集A)的编码数值包含所有另一种字符集(字符集B)的编码数值,并且两种字符集相同编码数值代表相同的字符时,则字符集A是字符集B的超级,或称字符集B是字符集A的子集。

例如WE8ISO8859P1、ZHS16CGB231280、ZHS16GBK都是US7ASCII的超集。 

如何使用字符集

01

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

数据库服务器字符集查询

SQL> select * from nls_database_parameters where parameter='NLS_CHARACTERSET';

SQL> select * from  database_properties;

查询结果中NLS_CHARACTERSET表示字符集,NLS_NCHAR_CHARACTERSET表示国家字符集

查看数据库的属性

select * from  database_properties;

select * from nls_database_parameters;

NLS_CHARACTERSET  数据库字符集

ZHS16GBK

NLS_NCHAR_CHARACTERSET  国家字符集

AL16UTF16

例:

create table test (c1 char(10) ,c2 nchar(10));

SQL> desc test;

 Name                                      Null?    Type

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

 C1                                                 CHAR(10)

 C2                                                 NCHAR(10)

insert into test values ('a','a');

commit;

SQL> select * from test;

C1         C2

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

a          a

在数据库存储的是不同的编码?

select dump(c1 ,1016) ,dump(c2,1016) from test ;

SQL> select dump(c1 ,1016) ,dump(c2,1016) from test ;

DUMP(C1,1016)

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

DUMP(C2,1016)

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

Typ=96 Len=10 CharacterSet=ZHS16GBK: 61,20,20,20,20,20,20,20,20,20

Typ=96 Len=20 CharacterSet=AL16UTF16: 0,61,0,20,0,20,0,20,0,20,0,20,0,20,0,20,0,

20,0,20

char---->ZHS16GBK

nchar ---->AL16UTF16

02

客户端字符集

    客户端字符集定义了客户端字符数据的编码方式,任何发自或发往客户端的字符数据均使用客户端定义的字符集编码,客户端可以看作是能与数据库直接连接的各种应用,例如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环境

         $NLS_LANG=“simplified chinese”_china.zhs16gbk

         $export NLS_LANG

         编辑oracle用户的profile文件

    2)Windows环境

         编辑注册表

         Regedit.exe -->  HKEY_LOCAL_MACHINE --> SOFTWARE --> ORACLE-HOME

或者在窗口设置:

set nls_lang=AMERICAN_AMERICA.ZHS16GBK 

修改NLS参数

    使用下列方法可以修改NLS参数

    (1)修改实例启动时使用的初始化参数文件

    (2)修改环境变量NLS_LANG

    (3)使用ALTER SESSION语句,在oracle会话中修改

    (4)使用某些SQL函数

    NLS作用优先级别:Sql function --> alter session --> 环境变量或注册表 --> 参数文件 --> 数据库默认参数

01

乱码产生与解决

    一个字符在客户端应用中显示取决于客户端操作系统,显示的字符要存储就依赖于另外两个字符集。

在传输过程中,客户端NLS_LANG主要用于进行转换判断,

如果NLS_LANG等于数据库字符集,则不进行任何转换,直接把字符插入数据库,如果不同则进行转换

转换主要任务:

  1. 如存在对应关系,则把相应二进制编码经过映射后传递给数据库。

  2. 如不存在对应关系,则传递一个替换字符(最常见的替换字符是"?"),直接以?存入数据库。

    例:

set NSL_LANG=American_America.ZHS16GBK

ue 16进制编辑器:

你好    C4 E3 BA C3

SQL> create table t(id int,name char(20));

Table created.

SQL> commit;

SQL> insert into t values(1,'你好');

1 row created.

SQL> commit;

SQL>  select id ,dump(name,1016) from t;

ID

----------

DUMP(NAME,1016)

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

1

Typ=96 Len=20 CharacterSet=ZHS16GBK: e4,bd,a0,e5,a5,bd,20,20,20,20,20,20,20,20,2

0,20,20,20,20,20

可以查出字符存储的字符集为:ZHS16GBK,客户端和服务器段一样,则不做转换。

SQL> select * from t;

ID NAME

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

1 你好

乱码解决:将客户端的操作系统修改为支持中文字符,并将客户端字符集修改成和操作系统一致的字符集。

os 字符集=nls_lang字符集  最好和数据库字符集相同,数据库字符集是他们超级。

文章转载自oracleEDU,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论