oracle中char和varchar2数据类型的区别

Oracle中char和varchar2数据类型有什么区别?有数据”test”分别存放到char(10)和varchar2(10)
类型的字段中,其存储长度及类型有何区别?

首先解释一下:

CHAR的长度是固定的,而VARCHAR2的长度是可以变化的。比如存储的字符串是:“liming”那么在char中占10个字符,包括“liming” + 3个空格。在varchar2中长度为7。

char的效率比varchar2的效率稍高。

char和varchar是一对矛盾体。但是存在即是合理。

VARCHAR2虽然比CHAR节省空间,但是假如一个VARCHAR2列经常被修改,而且每次被修改的数据的长度不同,这会引起‘行迁移’(Row Migration)现象,而这造成多余的I/O,是数据库设计和调整中要尽力避免的,在这种情况下用CHAR代替VARCHAR2会更好一些。

 

一下内容来自:http://blog.csdn.net/ningoo/article/details/1445922

char

char类型保存定长字符串,最小长度为1字节(或字符数),最长2000字节(注意这里是字节,而不是字符数),如果不指定,则默认为1。

SQL> create table t(name char);

表已创建。

SQL> desc t;
名称 是否为空? 类型
----------------------------------------- -------- ----------------------------
NAME CHAR(1)

SQL> create table t(name char(2001));
create table t(name char(2001))
*
第 1 行出现错误:
ORA-00910: 指定的长度对于数据类型而言过长

如果插入的字符串长度不足,会以空格填充。如果超过长度,则会报错。

SQL> insert into t values('aa');
insert into t values('aa')
*
第 1 行出现错误:
ORA-12899: 列 "SYS"."T"."NAME" 的值太大 (实际值: 2, 最大值: 1)

下面是例子展示了关于char类型的插入后续空格值的问题:
SQL> create table t(name char(20));

表已创建。

SQL> insert into t values('a');

已创建 1 行。

SQL> insert into t values('a ');

已创建 1 行。

SQL> select '"'||name||'"' from t where name='a';

'"'||NAME||'"'
----------------------
"a "
"a "

SQL> select '"'||name||'"' from t where name='a ';

'"'||NAME||'"'
----------------------
"a "
"a "

SQL> insert into t values(' a');

已创建 1 行。

SQL> select '"'||name||'"' from t where name='a';

'"'||NAME||'"'
----------------------
"a "
"a "

SQL> select '"'||name||'"' from t where name=' a';

'"'||NAME||'"'
----------------------
" a "

可以看到,如果插入的字符串最后带有空格,对于定长的字符串的比较,oracle会将较短的字符串右边填上空格,直到对比的两边的字符串长度一致。

varchar2和varchar

varchar2和varchar是同义词,都是指变长字符串类型。但是由于某种原因,varchar可能在后续版本中改变varchar的意思还是怎么的,oracle建议使用varchar2。

在使用varchar2类型时必须指定其长度(最小1字节或字符数,最大4000字节),不能像char一样省略,虽然concepts文档上说其默认为1。这里不知道oracle为什么会这样实现,我认为这应该算是一个缺陷。

SQL> drop table t;

表已删除。

SQL> create table t(name varchar);
create table t(name varchar)
*
第 1 行出现错误:
ORA-00906: 缺失左括号


SQL> create table t(name varchar2);
create table t(name varchar2)
*
第 1 行出现错误:
ORA-00906: 缺失左括号

由于varchar2不会在短于指定长度的字符串后面补齐空格,所以char类型中的后续空格问题不会在varchar2类型中发生。

SQL> create table t(name varchar2(20));

表已创建。

SQL> insert into t values('a');

已创建 1 行。

SQL> insert into t values('a ');

已创建 1 行。

SQL> select '"'||name||'"' from t where name='a';

'"'||NAME||'"'
----------------------
"a"

SQL> select '"'||name||'"' from t where name='a ';

'"'||NAME||'"'
----------------------
"a "

关于字符型数据的长度问题

前面在说到char/varchar2类型时,指定其长度可能是1字节或者1个字符数。在不同的编码方式中,一个字符可能占1字节,2字节,3字节甚至4字节。

SQL> select name,value$ from props$ where name='NLS_CHARACTERSET';

NAME VALUE$
------------------------------ ------------------------------
NLS_CHARACTERSET ZHS16GBK

SQL> create table t(name char(1 byte));

表已创建。

SQL> insert into t values('测');
insert into t values('测')
*
第 1 行出现错误:
ORA-12899: 列 "SYS"."T"."NAME" 的值太大 (实际值: 2, 最大值: 1)

SQL> create table t(name char(1 char));

表已创建。

SQL> insert into t values('测');

已创建 1 行。

SQL> create table t(name char(1));

表已创建。

SQL> insert into t values('测');
insert into t values('测')
*
第 1 行出现错误:
ORA-12899: 列 "SYS"."T"."NAME" 的值太大 (实际值: 2, 最大值: 1)

可以看到,由于一个汉字占两个byte,如果char/varchar2的长度是按byte计算的,那么就无法插入,如果是按字符数计算的,则可以插入。而在默认情况下,oracle是按byte计算长度的,这是由于参数nls_length_semantics的默认值是byte。

SQL> show parameter nls_length

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
nls_length_semantics string BYTE

但是,char类型的最大上限是2000字节,而不是2000字符数。

SQL> drop table t;

表已删除。

SQL> create table t(name char(2000 char));

表已创建。

SQL> insert into t values(lpad('测',2000,'测'));

已创建 1 行。

SQL> select length(name) from t;

LENGTH(NAME)
------------
1000

SQL> select lengthb(name) from t;

LENGTHB(NAME)
-------------
2000

SQL> insert into t values(lpad('测',2002,'测'));
insert into t values(lpad('测',2002,'测'))
*
第 1 行出现错误:
ORA-12899: 列 "SYS"."T"."NAME" 的值太大 (实际值: 2002, 最大值: 2000)

从上面的例子可以看出,最多只能插入1000个字符。顺便提一下,在lpad/rpad函数中,第二个参数也是指的字节数,而不是字符数。并且,lpad/rpad的输出也是varchar2类型的,所以第二个参数不能超过4000,如果超过,会被截断成4000。

在数据字典中,oracle还是会将按字符数计算的长度,按照系统当前的字符集选择,转换成按字节计算的长度。由于我目前的测试系统中使用的ZHS16GBK字符集是定长字符集,每个字符占两个字节,所以这里data length为2。在一些变长字符集中,比如UTF8,则是4(UTF8中一个字符最长占4个字节)
SQL> drop table t;

表已删除。

SQL> create table t(name char(1 char));

表已创建。

SQL> select TABLE_NAME,COLUMN_NAME,DATA_TYPE,DATA_LENGTH from dba_tab_columns where

table_name='T' a
nd owner=user;

TABLE_NAME COLUMN_NAM DATA_TYPE DATA_LENGTH
---------- ---------- ---------- -----------
T NAME CHAR 2


但是,oracle在判断插入的时候不是以dba_tab_columns中记录的data_length来做为限制条件的。看看UTF8下的试验结果:

SQL> select name,value$ from props$ where name='NLS_CHARACTERSET';

NAME VALUE$
------------------------------ ------------------------------
NLS_CHARACTERSET AL32UTF8

SQL> drop table t;

表已删除。

SQL> create table t(name char(1 char));

表已创建。

SQL> select TABLE_NAME,COLUMN_NAME,DATA_TYPE,DATA_LENGTH from dba_tab_columns where
2 table_name='T' and owner=user;

TABLE_NAME COLUMN_NAM DATA_TYPE DATA_LENGTH
---------- ---------- ---------- -----------
T NAME CHAR 4

SQL> insert into t values('aa');
insert into t values('aa')
*
第 1 行出现错误:
ORA-12899: 列 "SYS"."T"."NAME" 的值太大 (实际值: 2, 最大值: 1)

SQL> insert into t values('a');

已创建 1 行。

SQL> insert into t values('测');

已创建 1 行。

SQL> select dump(name) from t;

DUMP(NAME)
--------------------------------------------------------------------------------
Typ=96 Len=1: 97
Typ=96 Len=3: 230,181,139

可以看到,一个英文字符占一个字节,那么'aa'只占两个字节,却无法插入。'测'占3个字节,却能插入。所以在判断插入的数据是否符合长度要求时,oracle会根据定义的数据类型是按字节还是按字符数,然后参考系统当前的字符集设置来做出正确的判断。

实际上,oracle提供的求字符串长度的函数length,返回的也是字符个数,而非字节数:
SQL> select length('a') from dual;

LENGTH('A')
-----------
1

SQL> select length('测') from dual;

LENGTH('测')
------------
1

而lengthb返回的才是字节数:

SQL> select lengthb('a') from dual;

LENGTHB('A')
------------
1

SQL> select lengthb('测') from dual;

LENGTHB('测')
-------------
3

相关推荐
<p> <strong><span style="font-size:20px;color:#FF0000;">本课程主要针对计算机相关专业正在做毕设学生与需要项目实战练习Java学习者</span></strong> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">1. 包含:<span style="color:#FFFF00;background-color:#FF0000;">项目源码、</span><span style="color:#FFFF00;background-color:#FF0000;">项目文档、数据库脚本、软件工具</span>等所有资料</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">2. 手把手带你从零开始部署运行本套系统</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">3. 该项目附带源码资料可作为毕设使用</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">4. 提供技术答疑远程协助指导</span></strong></span><strong><span style="font-size:18px;"></span></strong> </p> <p> <br /> </p> <p> <span style="font-size:18px;"><strong>项目运行截图:</strong></span> </p> <p> <strong><span style="font-size:18px;">1)系统登陆界面</span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241015433522.png" alt="" /><br /> </span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">2)学生模块</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241015575966.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">3)教师模块</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016127898.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">4)系统管理员</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016281177.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016369884.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><br /> </span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">更多Java毕设项目请关注我毕设系列课程 <a href="https://edu.csdn.net/lecturer/2104">https://edu.csdn.net/lecturer/2104</a></span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><br /> </span></strong> </p>
<p> 课程演示环境:Windows10  </p> <p> 需要学习<span>Ubuntus</span>系统<span>YOLOv4-tiny</span>同学请前往《<span>YOLOv4-tiny</span>目标检测实战:训练自己数据集》 <span></span> </p> <p> <span> </span> </p> <p> <span style="color:#E53333;">YOLOv4-tiny</span><span style="color:#E53333;">来了!速度大幅提升!</span><span></span> </p> <p> <span> </span> </p> <p> <span>YOLOv4-tiny</span>在<span>COCO</span>上性能可达到:<span>40.2% AP50, 371 FPS (GTX 1080 Ti)</span>。相较于<span>YOLOv3-tiny</span>,<span>AP</span><span>FPS</span>性能有巨大提升。并且,<span>YOLOv4-tiny</span>权重文件只有<span>23MB</span>,适合在移动端、嵌入式设备、边缘计算设备上部署。<span></span> </p> <p> <span> </span> </p> <p> 本课程将手把手地教大家使用<span>labelImg</span>标注使用<span>YOLOv4-tiny</span>训练自己数据集。课程实战分为两个项目:单目标检测(足球目标检测)多目标检测(足球梅西同时检测)。<span></span> </p> <p> <span> </span> </p> <p> 本课程<span>YOLOv4-tiny</span>使用<span>AlexAB/darknet</span>,在<span>Windows10</span>系统上做项目演示。包括:<span>YOLOv4-tiny</span>网络结构、安装<span>YOLOv4-tiny</span>、标注自己数据集、整理自己数据集、修改配置文件、训练自己数据集、测试训练出网络模型、性能统计<span>(mAP</span>计算<span>)</span>先验框聚类分析。 <span> </span> </p> <p> <span> </span> </p> <p> 除本课程《<span>Windows</span>版<span>YOLOv4-tiny</span>目标检测实战:训练自己数据集》外,本人推出了有关<span>YOLOv4</span>目标检测系列课程。请持续关注该系列其它视频课程,包括:<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测实战:训练自己数据集》<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测实战:人脸口罩佩戴识别》<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测实战:国交通标志识别》<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测:原理与源码解析》<span></span> </p> <p> <span> <img alt="" src="https://img-bss.csdnimg.cn/202007061503586145.jpg" /></span> </p> <p> <span><img alt="" src="https://img-bss.csdnimg.cn/202007061504169339.jpg" /><br /> </span> </p>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页