本文适用于Oracle版本11.2.0.1.0,不保证在其它版本的适用性。
如果是字符串型字段,是设为varchar2还是nvarhcar2好,如果设置了最大长度是多少?网上众说纷纭,下文试图从实验入手,亲身获取第一手资料,免得被人误导。
让我们先建一个实验表:
create table test( id int, name nvarchar2(10), remark varchar2(10), primary key(id));
准备执行的SQL插入语句,大家可先预判下执行结果。
insert into test(id,name,remark) values(1,'离离原上草一岁一枯荣','离离原上草'); insert into test(id,name,remark) values(2,'离离原上草一岁一枯荣','离离原上草一'); insert into test(id,name,remark) values(3,'1234567890','离离原上草'); insert into test(id,name,remark) values(4,'12345678901','离离原上草'); insert into test(id,name,remark) values(5,'1234567890','1234567890'); insert into test(id,name,remark) values(6,'1234567890','12345678901');
第一句:insert into test(id,name,remark) values(1,'离离原上草一岁一枯荣','离离原上草');
成功,因为nvarchar2(10)与字符集无关,最多容纳10个汉字或英数字,'离离原上草一岁一枯荣'正好十个汉字,没有超过限度;而varchar2(10)最多容纳5个汉字或是十个英数字,'离离原上草'是五个汉字也没有超限,故成功插入。
执行结果:
SQL> insert into test(id,name,remark) values(1,'离离原上草一岁一枯荣','离离原上草'); 已创建 1 行。
第二句:insert into test(id,name,remark) values(2,'离离原上草一岁一枯荣','离离原上草一');
这一句remark里塞入了'离离原上草一',这是六个汉字,相当于12个英数字,所以超限了,故插入失败。
执行结果:
SQL> insert into test(id,name,remark) values(2,'离离原上草一岁一枯荣','离离原上草一'); insert into test(id,name,remark) values(2,'离离原上草一岁一枯荣','离离原上草一') * 第 1 行出现错误: ORA-12899: 列 "LUNA"."TEST"."REMARK" 的值太大 (实际值: 12, 最大值: 10)
第三句:insert into test(id,name,remark) values(3,'1234567890','离离原上草');
这一句name里塞'1234567890',这是正好十个英数字,没有超限;remark里塞'离离原上草',这是五个汉字相当于十个英数字,也没有超限,故成功插入.
执行结果:
SQL> insert into test(id,name,remark) values(3,'1234567890','离离原上草'); 已创建 1 行。
第四句:insert into test(id,name,remark) values(4,'12345678901','离离原上草');
这一句往name里塞'12345678901',这段文本是十一个英数字,超过限度,故插入失败。
执行结果:
SQL> insert into test(id,name,remark) values(4,'12345678901','离离原上草'); insert into test(id,name,remark) values(4,'12345678901','离离原上草') * 第 1 行出现错误: ORA-12899: 列 "LUNA"."TEST"."NAME" 的值太大 (实际值: 11, 最大值: 10)
第五句:insert into test(id,name,remark) values(5,'1234567890','1234567890');
这一句往name和remark里塞的都是'1234567890',这段文本是十位英数字,故不超限,能成功插入。
执行结果:
SQL> insert into test(id,name,remark) values(5,'1234567890','1234567890'); 已创建 1 行。
第六句:insert into test(id,name,remark) values(6,'1234567890','12345678901');
这一句name不超,但remark里塞'12345678901',这是十一个英数字,已经超过,故插入失败。
执行结果:
SQL> insert into test(id,name,remark) values(6,'1234567890','12345678901'); insert into test(id,name,remark) values(6,'1234567890','12345678901') * 第 1 行出现错误: ORA-12899: 列 "LUNA"."TEST"."REMARK" 的值太大 (实际值: 11, 最大值: 10)
最后留存表中数据:
SQL> select * from test; ID NAME REMARK ---------- -------------------- ---------- 1 离离原上草一岁一枯荣 离离原上草 3 1234567890 离离原上草 5 1234567890 1234567890
结论:
nvarchar2(MAX) 不分字符集,规定多少个就是多少个,英语字母数字汉字平假名片假名都一视同仁,没有换算时乘二除二的麻烦;
varchar2(MAX) 区分字符集,能容纳MAX个英数字,只能容纳MAX/2个汉字,换算有点烦。
为省心计,最好文本字段都按nvarchar2类型来设定。
扩展:
大家都知道oracle里有个仿佛是硬编码的字符串上限,即最多容纳4000个英数字,即varchar2(n)型字段,n的上限便是4000;nvarchar2(N),N的上限便是4000/2=2000。
咱们可以验证一下nvarchar2型字段:
SQL> create table tb( 2 id int, 3 remark nvarchar2(2001), 4 primary key(id)); remark nvarchar2(2001), * 第 3 行出现错误: ORA-00910: 指定的长度对于数据类型而言过长 SQL> create table tb( 2 id int, 3 remark nvarchar2(2000), 4 primary key(id)); 表已创建。
这说明nvarchar2类型字段能容纳字符个数为2000个,对中英文都一样。
再验证一下varchar2型字段:
SQL> create table tb2( 2 id int, 3 name varchar2(4001), 4 remark nvarchar2(2000), 5 primary key(id)); name varchar2(4001), * 第 3 行出现错误: ORA-00910: 指定的长度对于数据类型而言过长 SQL> create table tb2( 2 id int, 3 name varchar2(4000), 4 remark nvarchar2(2000), 5 primary key(id)); 表已创建。
这说明varchar2类型最多可容纳4000个英数字,合2000个汉字。
-END-