日期:2014-05-16 浏览次数:20719 次
今天上午,之前测试都没有问题的过程,今天报错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