这部分可以看作 SQL 语句的基本语法规则。主要包括:
1、数据类型
Oracle 数据库管理的每个数值都有一种数据类型,数据类型实际上限定了该数据的取值范围、长度、精度乃至格式等要求。可以八卦一下,为什么要区分数据类型,都用一种数据类型(比如字符类型)来处理数据不是更简单吗?Alex Kriegel 和 Boris M. Trukhnow的《SQL Bible》对此有描述,主要是由于两个原因:一是历史原因,为了更有效地利用存储空间,比如如果把数字也用字符格式存储而不用二进制形式存储的话,那么-32768~32768之间的数字就需要6个字节(二进制形式存储只需要2个字节);二是因为逻辑一致性,每种数据类型都有自身的规则、排序次序、与其他数据类型的关系、固有的转换法则等,处理同样类型的集合比处理各种混在一起数据类型要方便得多。
Oracle 数据库数据类型涉及到的问题包括:
此外,还有个外部数据类型的概念(external data type),注意要不要混淆外部数据类型与内置数据类型、用户定义类型。
1-1、有哪些内置的数据类型?
包括:
1-1-1、字符类型
字符类型分为两种:以ASCII编码存储的和以民族字符编码存储的。
每种字符类型又有两种串:定长的和变长的。这样分下来,就一共有4种:char、varchar2、nchar 和 nvarchar2。
使用 Oracle SQL 中的 dump 函数可以返回列或者属性的类型码(code),上述四种类型对应的类型码分别是 char 和 nchar 都是 96,varchar2 和 nvarchar2 都是 1。
字符类型的特点:
nchar 和 char 的区别在于 nchar 不能指定长度计量单位,它的长度计量单位就是 char,而且长度不能超过2000字节;也就是说大部分情况下,不能超过 nchar(1000)。
nvarchar2 和 varchar2 的区别在于 nvarchar 不能指定长度计量单位,它的长度计量单位就是 char,而且长度不能超过4000字节;也就是说大部分情况下,不能超过 nvarchar2(2000)。
如果向 char 类型的数据中插入的实际字符串比定义的长度短,那么 oracle 会在数值中填充空格,确保每个值都达到定义中指定的长度;但如果向 varchar2 类型的数据中插入较短的字符串,oracle 不会填充空格。可以看出来,使用 varchar2 明显对空间的使用效率要高,一个有意思的问题是,既然有了高效率的 varchar2,那为嘛还要有 char 呢?有兴趣的读者可以参考CSDN上的这篇博文。
这里啰嗦几句关于计量单位 BYTE 和 CHAR 的问题。
BYTE 计量单位,表示按字节来计数;而 CAHR 计量单位,表示按字符来计数,这种计量方式与环境变量的字符集相关。举例子:
首先查看下当前会话的字符集:
scott@ORA11G> select userenv('language') from dual;
USERENV('LANGUAGE')
----------------------------------------------------
AMERICAN_AMERICA.WE8MSWIN1252
按照 Oracle 字符集命名规则 <语言><比特位数><编码>可知,当前环境是西欧
scott@ORA11G> create table t (cbyte char( 3 byte),cchar char (3 char) );
Table created.
现在往里面插数据,先插 ASCII 字符串:
scott@ORA11G> insert into t(cbyte) values('123');
1 row created.
向表中的 cbyte 列插入字符串'123'没有问题,因为该列的长度为 3byte,下面还是向 cbyte 列插入'1234'试试:
scott@ORA11G> insert into t(cbyte) values('1234');
insert into t(cbyte) values('1234')
*
ERROR at line 1:
ORA-12899: value too large for column "SCOTT"."T"."CBYTE" (actual: 4, maximum: 3)
报错了!说明要插入的数据长度不能超过 3 byte
现在来考察 cchar 列,向 ccahr 列插入 '123',也没问题:
scott@ORA11G> insert into t(cchar) values('123');
1 row created.
scott@ORA11G> insert into t(cchar) values('1234');
insert into t(cchar) values('1234')
*
ERROR at line 1:
ORA-12899: value too large for column "SCOTT"."T"."CCHAR" (actual: 4, maximum: 3)
这两个例子说明,在编码长度为8位的环境中,CHAR 和 BYTE 的长度是一个意思,都是1个字节。
那么此时如果插入多字节字符会是什么情况呢?
首先我们来看看环境(Linux 中)的 LANG 变量,
scott@ORA11G> !echo $LANG
en_US.utf8
是 UTF8 编码,那么我现在如果输入中文字符的话,应该是 UTF8 编码的,试一下,首先试 cbyte:
scott@ORA11G> insert into t(cbyte) values('一二');
insert into t(cbyte) values('一二')
*
ERROR at line 1:
ORA-12899: value too large for column "SCOTT"."T"."CBYTE" (actual: 6, maximum: 3)
这里传入了2个字符,但是长度为6个字节,因此无法插入,现在试试 cchar:
scott@ORA11G> insert into t(cchar) values('一二');
insert into t(cchar) values('一二')
*
ERROR at line 1:
ORA-12899: value too large for column "SCOTT"."T"."CCHAR" (actual: 6, maximum: 3)
现在我们到另一个数据库环境下面来继续试验,这个数据库的字符集是 ZHS16GBK 字符集,可以看出这是个16位的字符集,查看下会话变量
scott@ORA11GR2> select userenv('language') from dual;
USERENV('LANGUAGE')
----------------------------------------------------
SIMPLIFIED CHINESE_CHINA.ZHS16GBK
scott@ORA11GR2> create table t (cbyte char( 3 byte),cchar char (3 char) );
表已创建。
插入4个 ASCII 字符到 CBYTE 中,可以预见不会成功:
scott@ORA11GR2> insert into t(cbyte) values('1234');
insert into t(cbyte) values('1234')
*
第 1 行出现错误:
ORA-12899: 列 "SCOTT"."T"."CBYTE" 的值太大 (实际值: 4, 最大值: 3)
那插入 4 个 ASCII 字符到 CCHAR 中会是什么效果呢?
scott@ORA11GR2> insert into t(cchar) values('1234');
insert into t(cchar) values('1234')
*
第 1 行出现错误:
ORA-12899: 列 "SCOTT"."T"."CCHAR" 的值太大 (实际值: 4, 最大值: 3)
scott@ORA11GR2> insert into t(cbyte) values('一二');
insert into t(cbyte) values('一二')
*
第 1 行出现错误:
ORA-12899: 列 "SCOTT"."T"."CBYTE" 的值太大 (实际值: 4, 最大值: 3)
可以看到,cbyte 依然不行,因为 '一二' 占了4个字节,超出了 cbyte 定义的长度 3。但是 cchar 会怎样呢?
scott@ORA11GR2> insert into t(cchar) values('一二');
已创建 1 行。
scott@ORA11GR2> insert into t(cchar) values('一二三');
已创建 1 行。
scott@ORA11GR2> insert into t(cchar) values('一二三四');
insert into t(cchar) values('一二三四')
*
第 1 行出现错误:
ORA-12899: 列 "SCOTT"."T"."CCHAR" 的值太大 (实际值: 4, 最大值: 3)
我们看到,将双子节字符插入 cchar 中时,不仅 '一二' 成功了,'一二三' 也成功了,但是 '一二三四'失败了,失败的原因说有4个字符,超出了3个字符的限制。