【Oracle】亲手做实验来感受nvarchar2和varchar2的区别

本文适用于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-

原文地址:https://www.cnblogs.com/heyang78/p/15269468.html