Oracle的数据类型(一):char/varchar2

Oracle charvarchar2的区别 charVarchar2Oracle的内部存储格式都样都是数据长度length+实际数据data,其中数据长度length用1-3个字节表示,length255用3个字节表示。 Thomas Kyte的建议是忘记有char类型的存在,在切需要字符的地方都是用varchar2格式。 “不过,如果混合使用并匹配 VARCHAR2CHAR ,你就会不断地遭遇这个问题。不仅如此,开发人员 现 在还必须在应用中考虑字段宽度。如果开发人员喜欢使用 RPAD() 技巧将绑定变量转换为某种能与 阅读详情

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

Oracle数据库从入门到精通系列之十四:CHARVARCHAR2、NCHAR和NVARCHAR2 不论在表段还是索引段中,CHAR都会占用最大的存储空间,这就够糟糕了,避免使用CHAR/NCHAR类型还有另外个很重要的原因:CHAR/NCHAR类型还会给使用这些数据的应用带来混乱,原因与字符串的比较的规则有关,也与执行字符串比较多严格程度有关。使用诸如UTF-8的多字节字符集时,建议在VARCHAR2/CHAR定义中使用CHAR修饰符,也就是说使用VARCHAR2(80 CHAR),而不是VARCHAR2(80),因为是要定义个实际上能存储80字符数据的列。 阅读详情

相关推荐

Oracle 常见错误代码处理 00010-04098

目录 ORA-28040: No matching authencation protocol ORA-28040: No matching authencation protocol 1、Spring boot 应用启动时候正常,但是页面访问后台接口,程序再访问数据库时,控制台报错如下:没有匹配的身份验证协议 Caused by: java. sql. SQLExceptiona ORA-28040: No matching authentication protocol at oracle...

蚩尤后裔-汪茂雄 1万+

ORACLE数据库报错ORA-00910: specified length too long for its datatype

ORACLE数据库报错ORA-00910: specified length too long for its datatype 原因分析 先直接说下对于ORA-00910报错的原因:在于Oracle数据库中VARCHAR2最大存储4000字节长度的数据 关于OracleVARCHAR2详细说明 根据官方说明,在Oracle数据库中VARCHAR2类型字段可声明为bytechar,如:varchar2(100)[ varchar2(100 byte) ] - 100字节长度varchar2(100 c

黑伴白的博客 7118

oracle ora 00910,ORA-00910: 指定长度对于数据类型而言过长

目标端创建表报错:SQL> create table KK_12(3idNUMBER(20) not null,4codeNVARCHAR2(255),5nameNVARCHAR2(255),6dictvalue_id NUMBER(8) not null,7attr_idNUMBER(20) not null,8seqNUMBER(6),9creator_idN...

weixin_34314939的博客 3985

Oracle char(1)varchar(1)的区别

1.char(1)varchar(1)的性能样。 2.当char(1)变成char(2)的时候会在所有数据前加个空格,所以会对整张表进行锁表 综上:在Oracle中设计表字段的时候尽量不要使用char(1),而是用varchar(1)来代替。

大林的博客 4235

oraclecharvarcharvarchar2区别

1.varchar2把所有字符都占两字节处理(般情况下)varchar只对汉字和全角等字符占两字节,数字,英文字符等都是个字节; 2.VARCHAR2把空串等同于null处理,而varchar仍按照空串处理; 3.VARCHAR2字符要用几个字节存储,要看数据库使用的字符集, 大部分情况下建议使用varchar2类型,可以保证更好的兼容性。 注意: 在oraclevarchar2的最大长...

u012374512的博客 1万+

OracleCHARVARCHAR2的区别

CHARVARCHAR2都是Oracle的数据存储格式。CHAR是定长的,VARCHAR2是变长。都可以存储字符串。      需要注意的是使用CHAR的时候。Select查询要注意定长的格式。查询字符串的长度要刚好。多了少了都不能查不到数据。例如字段A为CHAR(10)。存“abcdefg”,长度不满10。Oracle会用空格补满10位。你用"abcefg"作为查询字段时是查不出来的。这就是我...

rui_xiao的博客 1万+

详解Oracle数据库int、number类型和charvarcharvarchar2类型的区别

概述 简单汇总下oracle数据库int、number和charvarcharvarchar2的区别 1、oracle中int与number的区别 oracle本来就没有int类型,为了与别的数据库兼容,新增了int类型作为number类型的子集。int类型只能存储整数;number可以存储浮点数,也可以存储整数; number(8,1)存储小数位为1位,总长度为8的浮点数,如果小数位数不足,则用0补全; number(8)存储总长度为8的整数; int相当于number(22),存储总长度22的整数

淡定波的博客 1万+

Oracle字段类型charvarchar2、nvarchar2的区别与使用

1、和VARCHAR不同的是,VARCHAR2把空串等同于null处理,这也是为什么ORACLE推荐使用VARCHAR2类型的原因。存储大小是输入数据的实际长度2 个字节,用于反映存储的数据的长度。例如varchar2(3 char),可以存储3个字符(包括字母和汉字),如'啊啊啊'、'aaa'、'啊aa',与字节(byte长度无关;与上面不同的是,是根据Unicode标准所进行的定义的类型,通常用于支持多国语言类似系统的定义。固定长度,非 Unicode 字符数据,长度为 n 个字节。

xiying15270873284的博客 9417

Oracle数据类型 CHARVARCHARVARCHAR2的区别

varchar对空串不处理,varchar2将空串当做null来处理。varchar存放固定长度的字符串,最大长度2000,varchar2是存放可变长度的字符串,最大长度是4000。存“aaabbb”,长度不满10,Oracle会用空格补满10位。:使用CHAR的时候,Select查询要注意定长的格式,查询字符串的长度要刚好,多了少了都不能查不到数据。VARCHAR 是标准sql里的,VARCHAR2Oracle所提供的独有的数据类型CHAR是定长的,VARCHAR2是变长,都可以存储字符串。

qq_43312876的博客 3800

Oraclevarcharvarchar2

CHARVARCHARVARCHAR2区别: 1.CHAR长度是固定的,而VARCHAR2长度是可以变化的, 比如,存储字符串“abc",对于CHAR (20),表示你存储的字符将占20个字节(包括17个空字符),而同样的VARCHAR2 (20)则只占用3个字节的长度20只是最大值,当你存储的字符小于20时,按实际长度存储。 2CHAR的效率比VARCHAR2的效率稍

光何 5263

oracle mysql中的charvarcharvarchar2的区别

MySQLchar是定长的,varchar是变长的。varchar2应该是varchar的升级,似乎只有ORACLE才有,这里不作讨论。 char定长存储,速度快,但是存在定的空间浪费,适用于字段不是很大,对速度要求高的场合。速度快是因为其在物理上是按定长存储的,这样,就可以根据偏移址次取出固定长度的字符。 varchar变长存储,所以效率不如charvarchar在存储时,在物理

leifuchild的专栏 4841

oraclechar,varchar,varchar2的区别

1.char长度固定,varchar2长度可变。例如,存储字符串“123”,char(10)表示存储的内容占10个字节:123 (包含7个空格)varchar2(20)只占用3个字节:123当存储小于10时,按实际长度存储。综上,可以判断出charvarchar2效率高但浪费空间。 注:varchar最长为4000字节,char最长为2000字节 2.对于varcharvarchar2暂时未测出不同之处。varchar可以与其他数据库兼容,varchar2oracle独有的。oracl...

qq_39509702的博客 2093

oraclecharvarchar2数据类型的区别

Oraclecharvarchar2数据类型有什么区别?有数据”test”分别存放到char(10)varchar2(10) 类型的字段中,其存储长度及类型有何区别? 首先解释下: CHAR长度是固定的,而VARCHAR2长度是可以变化的。比如存储的字符串是:“liming”那么在char中占10个字符,包括“liming” + 3个空格。在varchar2长度为7。 cha

David_Tsai23的专栏 2250

Oracle中的CHAR,NCHAR,VARCHAR,VARCHAR2,NVARCHAR2

(1)OracleCHAR,NCHAR,VARCHAR,VARCHAR2,NVARCHAR2 URL:http://blog.163.com/blade_ralf/blog/static/89741687200962064628485/Oracle   2009-07-20 18:46    在OracleCHAR,NCHAR,VARCHAR,VARCHAR2,NVARCHAR2这五种类型的区别1.CHAR(size)VARCHAR(size)的区别    CHAR为定长的字段,最大长度2K字节; 

zhoubo200的专栏 1309

ORACLE CHAR,VARCHAR,VARCHAR2,NVARCHAR类型的区别与使用

区别:   1.CHAR长度是固定的,而VARCHAR2长度是可以变化的, 比如,存储字符串“abc",对于CHAR (20),表示你存储的字符将占20个字节(包括17个空字符),而同样的VARCHAR2 (20)则只占用3个字节的长度20只是最大值,当你存储的字符小于20时,按实际长度存储。   2CHAR的效率比VARCHAR2的效率稍高。   3.目前VARCHARVARCHAR2

xiaomin1991222的专栏 5267

Oracle字符类型详解:VARCHARVARCHAR2CHAR的区别

Oracle数据库中,VARCHARVARCHAR2CHAR是三种常用的字符数据类型,它们在存储方式、长度限制和使用场景上有着显著区别。

chinalog的专栏 1753

charvarcharvarchar2类型对空格的处理

在今天开发过程中,发现了查询结果很怪异,GOOGLE下才知道是OracleCHAR类型处理的问题,在oracle中对CHAR的处理是自动添加空格,比如char(8)存储'2007-11',则在后面自动添加空格,所以导致以下很多查询怪异问题(在表test中有字段month为char(8),存储着'2007-11'条数据):         select * from test where

hanchuang213的博客 3638
上一篇: 关于External Table
下一篇: Oracle10g新特性:临时表空间组(temporary tablespace group)
NinGoo
博客等级 码龄22年 31粉丝 78原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值