日期:2014-05-16  浏览次数:20603 次

不同字符集下字符串类型的比对以及存汉字的比较

       今天上午,之前测试都没有问题的过程,今天报错ora-06052的异常,查询之后发现原来是同一个字段在不同的表中定义的长度不一样,一个表中定义的是512,另一个表中定义的是500,现在分别用这两个字段定义了两个变量,当用512的变量给500的变量赋值时,如果赋值超过500就出问题了(确实超过500)。

        随后我查了一下char,varchar,varchar,nvarchar这四种字符类型,以及这四种类型在utf8和gbk两种字符集下存储中文的情况,length和lengthb函数。

ora-12899:是向表中插入的值超过了字段的长度。

ora-06052:是在赋值时值超过了变量的长度。


length:统计的是字符串中字符的个数。

lengthb:统计的是字符串的字节数。


char2(10),varchar(10),varchar2(10)的字段:

在gbk数据库中可以存5个汉字,lengthb统计到每个汉字是2个字节。

在utf8数据库中可以存3个汉字,lengthb统计到每个汉字是3个字节。


nvarchar2(10)的字段:

在gbk数据库中可以存10个汉字。

在utf8数据库中可以存10个汉字。

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

char:定长字符型,[1,2000]字节,不足则在后面补空格。

varchar:不定长字符型,[1,2000]字节。

varchar2:不定长字符型,[1,4000]字节,在pl/sql中最大长度是32767(没有测试)。

nvarchar:不定长字符型,[1,4000]字符。从下面测试情况看,在这两个不同字符集中都是按照2个字节来存储数据。


--这个地方不明白,utf8下不是每个汉字三个字节吗,怎么这里是两个字节。



---下面是测试语句

--查看数据库服务端的字符集
select userenv('language') from dual; 
--查看dmp的字符集
select nls_charset_name(to_number('0354','xxxx')) from dual; 
--查看数据库字符集
select * from nls_database_parameters;
--查看客户端字符集
select * from nls_instance_parameters;
--查看会话字符集
select * from nls_session_parameters;


drop table ttt1 purge;
drop table ttt2 purge;
drop table ttt3 purge;
drop table ttt4 purge;

create table ttt1(name char(10));

insert into ttt1 values('123');
insert into ttt1 values('我爱你');
insert into ttt1 values('我爱你我你');
select name,length(name),lengthb(name),dump(name) from ttt1;

create table ttt2(name varchar(10));
insert into ttt2 values('123');
insert into ttt2 values('我爱你');
insert into ttt2 values('我爱你我爱你');
insert into ttt2 values('我爱你我你');

select name,length(name),lengthb(name),dump(name) from ttt2;


create table ttt3(name varchar2(10));
insert into ttt3 values('123');
insert into ttt3 values('我爱你');
insert into ttt3 values('我爱你我爱你');
insert into ttt3 values('我爱你我你');

select name,length(name),lengthb(name),dump(name) from ttt3;

create table ttt4(name nvarchar2(10));
insert into ttt4 values('123');
insert into ttt4 values('我爱你');
insert into ttt4 values('我爱你我爱你');
insert into ttt4 values('我爱你我你');
insert into ttt4 values('我爱你我你我爱你我你');
insert into ttt4 values('我爱你我你我爱你我你1');

select name,length(name),lengthb(name),dump(name) from ttt4;

commit;

在gbk字符集数据库中测试的结果

SQL> --查看数据库服务端的字符集
SQL> select userenv('language') from dual;
 
USERENV('LANGUAGE')
----------------------------------------------------
SIMPLIFIED CHINESE_CHINA.ZHS16GBK
SQL> --查看dmp的字符集
SQL> select nls_charset_name(to_number('0354','xxxx')) from dual;
 
NLS_CHARSET_NAME(TO_NUMBER('03
----------------------------------------
ZHS16GBK
SQL> --查看数据库字符集
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              10.2.0.4.0