
一、什么是字符集
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等于数据库字符集,则不进行任何转换,直接把字符插入数据库,如果不同则进行转换
转换主要任务:
如存在对应关系,则把相应二进制编码经过映射后传递给数据库。
如不存在对应关系,则传递一个替换字符(最常见的替换字符是"?"),直接以?存入数据库。
例:
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字符集 最好和数据库字符集相同,数据库字符集是他们超级。





