概述
通过实例全面而深入的分析oralce的基本数据类型及它们的存储方式以ORACLE G为基础介绍oralce g引入的新的数据类型让你对oracle数据类型有一个全新的认识揭示一些不为人知的秘密和被忽略的盲点从实用和优化的角度出发讨论每种数据类型的特点从这里开始oracle之旅!
第一部份 字符类型
§ char
定长字符串会用空格来填充来达到其最大长度最长个字节
. 新建一个测试表test_char只有一个char类型的列长度为
SQL> create table test_char(colA char());
Table created
. 向这个表中插入一些数据
SQL> insert into test_char values(a);
row inserted
SQL> insert into test_char values(aa);
row inserted
SQL> insert into test_char values(aaa);
row inserted
SQL> insert into test_char values(aaaa);
row inserted
SQL> insert into test_char values(aaaaaaaaaa);
row inserted
注意最多只能插入个字节否是就报错
SQL> insert into test_char values(aaaaaaaaaaa);
insert into test_char values(aaaaaaaaaaa)
ORA: value too large for column PUB_TESTTEST_CHARCOLA (actual: maximum: )
. 使用dump函数可以查看每一行的内部存数结构
SQL> select colA dump(colA) from test_char;
COLA DUMP(COLA)
a Typ= Len=:
aa Typ= Len=:
aaa Typ= Len=:
aaaa Typ= Len=:
aaaaaaaaaa Typ= Len=:
注意Typ= 表示数据类型的IDOracle为每一种数据类型都进行了编号说明char类型的编号是
Len = 表示所在的内部存储的长度(用字节表示)虽然第一例只存了一个字符a但是它还是占用了个字节的空间
表示内部存储方式可见oracle的内部存储是以数据库字符集进行存储的
正好是字符a的ASCII码
可以使用chr函数把ASCII码转成字符
SQL> select chr() from dual;
CHR()
a
要想知道一个字符的ASCII码可以使用函数ascii
SQL> select ascii(a) from dual;
ASCII(A)
正好是空格的ascii码值
Char类型是定长类型它总会以空格来填充以达到一个固定宽度
使用char类型会浪费存储空间
Oracle的数据类型的长度单位是字节
SQL> select dump(汉) from dual;
DUMP(汉)
Typ= Len=:
可见一个汉字在oracle中是占用了两个字节的
英文字母或符号只占用一个字节
Char()最多可存放个汉字
§ varchar
是一种变长的字符类型最多可占用字节的存储空间
创建一个表只有一列类型为varchar长度为
SQL> create table test_varchar( col varchar());
Table created
插入一些数据
SQL> insert into test_varchar values(a);
row inserted
SQL> insert into test_varchar values(aa);
row inserted
SQL> insert into test_varchar values(aaa);
row inserted
SQL> insert into test_varchar values(aaaaaaaaaa);
row inserted
SQL> insert into test_varchar values(aaaaaaaaaaa);
用dump函数查看每一行的内部存储结构
SQL> select col dump(col) from test_varchar;
COL DUMP(COL)
a Typ= Len=:
aa Typ= Len=:
aaa Typ= Len=:
aaaaaaaaaa Typ= Len=:
Typ=说明varchar类型在oracle中的类型编号为
Len代表了每一行数据所占用的字节数
后面是具体的存储值
由此可见varchar是存多少就占用多少空间比较节省空间的不会像char那样用空格填充
§ byte 和char
在g中字符类型的宽度定义时可以指定单位
Byte就是字节
Char就是字符
Varchar( byte) 长度为个字节
Varchar( char) 长度为个字符所占的长度
Char( byte)长度为个字节
Char( char) 长度为个字符所占的长度
一个字符占用多少个字节是由当前系统采用的字符集来决定的
如一个汉字占用两个字节
查看当前系统采用的字符集
SQL> select * from nls_database_parameters where parameter =NLS_CHARACTERSET;
PARAMETER VALUE
NLS_CHARACTERSET ZHSGBK
如果在定义类型时不指定单位默认是按byte即以字节为单位的
采用char为单位的好处是使用多字节的字符集
比如在ZHSGBK字符集中一个汉字占用两个字节
把数据表的某一列长度定义为可存放个汉字通过下面的定义就可以了
Create table test_varchar(col_char varchar( char));
这样相对简单一些在数据库表设计时需要注意
继续实验新建一个表包含两列一列采用byte为单位一列采用char为单位
SQL> create table test_varchar (col_char varchar( char)col_byte varchar( byte));
Table created
Col_char列定义为可存放个字符
Col_byte 列定义为可存放个字节的字符
当前的系统采用字符集为ZHSGBK所以一个字符占两个字节
试着在表中插入一些数据
SQL> insert into test_varchar values(aa);
row inserted
SQL> insert into test_varchar values(袁a);
row inserted
SQL> insert into test_varchar values(袁袁袁袁袁袁袁袁袁袁aaaaaaaaaa);
row inserted
SQL> insert into test_varchar values(袁袁袁袁袁袁袁袁袁袁袁袁袁袁袁袁袁袁袁袁);
insert into test_varchar values(袁袁袁袁袁袁袁袁袁袁袁袁袁袁袁袁袁袁袁袁)
ORA: value too large for column PUB_TESTTEST_VARCHARCOL_BYTE (actual: maximum: )
第一次 在两列中都插入字符a
第二次 在col_char列插入字符袁在col_byte插入字符a
第三次 在col_char列中插入个中文字符袁在col_byte插入个字符a
第四次 在两列中都插入中文字符袁时报错了第二列长度不够
再看看每一行的存储结构
SQL> select col_char dump(col_char) from test_varchar;
COL_CHAR DUMP(COL_CHAR)
a Typ= Len=:
袁 Typ= Len=:
袁袁袁袁袁袁袁袁袁袁 Typ= Len=:
当我们在col_char列插入个汉字时它的长度为
尽管我们在定义的时候是采用varchar(char)
由此可见oracle是根据当前数据库采用的字符集每个字符的所占字节数 X 字段长度来决定了该字段所占的字节数
在本例中varchar(char)相当于varchar()
不信我们可以试试看
SQL> desc test_varchar;
Name Type Nullable Default Comments
COL_CHAR VARCHAR() Y
COL_BYTE VARCHAR() Y
当采用多字节的字符集时定义字段长度还是采用char为单位指定为佳因为可以避免字段长度的问题
当不知道当前数据库采用的字符集一个字符占用多少字节时可以使用lengthb函数
SQL> select lengthb(袁) from dual;
LENGTHB(袁)
§ char还是varchar
新建一个表一列为char类型一列为varchar类型
SQL> create table test_char_varchar(char_col char()varchar_col varchar());
Table created
向该表中的两列都插入相关的数据
SQL> insert into test_char_varchar values(Hello WorldHello World);
row inserted
SQL> select * from test_char_varchar;
CHAR_COL VARCHAR_COL
Hello World Hello World
以char_col列为条件查询
SQL> select * from test_char_varchar where char_col =Hello World;
CHAR_COL VARCHAR_COL
Hello World Hello World
以varchar_col列为条件查询
SQL> select * from test_char_varchar where varchar_col =Hello World;
CHAR_COL VARCHAR_COL
Hello World Hello World
似乎char 和varchar类型没有什么两样再看看下面的语句
SQL> select * from test_char_varchar where varchar_col =char_col;
CHAR_COL VARCHAR_COL
这已经看出他们并不一样这涉及到字符串比较的问题
因为已经发生了隐式转换在与char列char_col进行比较时char_col列的内容已经转换成了char()在Hello World后面以空格进行填充了而varchar_col列并没有发生这种转换
如果要让char_col列与varchar_col列相等有两种方法
第一种是使用trim把char_col列的空格去掉
第二种是使遥rpad把varchar_col列用空格进行填充长度为的字符
SQL> select * from test_char_varchar where trim(char_col) = varchar_col;
CHAR_COL VARCHAR_COL
Hello World Hello World
SQL> select * from test_char_varchar where char_col = rpad(varchar_col);
CHAR_COL VARCHAR_COL
Hello World Hello World
如果使用trim函数如果char_col列上有索引那么索引将不可用了
此外还会在绑定变量时出现问题