Oracle数据类型及存储方式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle数据类型及存储方式相关的知识,希望对你有一定的参考价值。
参考技术A概述
通过实例 全面而深入的分析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_TEST TEST_CHAR COLA (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= 表示数据类型的ID Oracle为每一种数据类型都进行了编号 说明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 ZHS GBK
如果在定义类型时 不指定单位 默认是按byte 即以字节为单位的
采用char为单位的好处是 使用多字节的字符集
比如 在ZHS GBK字符集中 一个汉字占用两个字节
把数据表的某一列长度定义为可存放 个汉字 通过下面的定义就可以了
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 列 定义为可存放 个字节的字符
当前的系统采用字符集为ZHS GBK 所以一个字符占两个字节
试着在表中插入一些数据
SQL> insert into test_varchar values( a a );
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_TEST TEST_VARCHAR COL_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 World Hello 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列上有索引 那么索引将不可用了
lishixinzhi/Article/program/Oracle/201311/17771
Oracle基本数据类型
一 字符串类型
字符串数据类型还可以依据存储空间分为固定长度类型(CHAR/NCHAR) 和可变长度类型(VARCHAR2/NVARCHAR2)两种.
所谓固定长度:是指虽然输入的字段值小于该字段的限制长度,但是实际存储数据时,会先自动向右补足空格后,才将字段值的内容存储到数据块中。这种方式虽然比较浪费空间,但是存储效率较可变长度类型要好。同时还能减少数据行迁移情况发生。
所谓可变长度:是指当输入的字段值小于该字段的限制长度时,直接将字段值的内容存储到数据块中,而不会补上空白,这样可以节省数据块空间。
1.1:CHAR类型 CHAR(size [BYTE | CHAR])
CHAR类型,定长字符串,会用空格填充来达到其最大长度。非NULL的CHAR(12)总是包含12字节信息。CHAR字段最多可以存储2,000字节的信息。如果创建表时,不指定CHAR长度,则默认为1。另外你可以指定它存储字节或字符,例如 CHAR(12 BYTYE) CHAR(12 CHAR).一般来说默认是存储字节,你可以查看数据库参数
NLS_LENGTH_SEMANTICS的值。
- SQL> show parameter nls_length_semantics;
- NAME TYPE VALUE
- ------------------ ----------- -----------------
- nls_length_semantics string BYTE
- eg:
- CREATE TABLE TEST
- (
- NAME_OLD CHAR(10),
- NAME_NEW CHAR(10 CHAR)
- )
- INSERT INTO TEST
- ( NAME_OLD, NAME_NEW)
- SELECT ‘ABCDEFGHIJ‘ , ‘你清除字节与字符‘ FROM DUAL;
- COMMIT;
- INSERT INTO TEST
- ( NAME_OLD, NAME_NEW)
- SELECT ‘你清除字节与字符‘ , ‘ABCDEFGHIJ‘ FROM DUAL;
- ORA-12899: 列 "SYS"."TEST"."NAME_OLD" 的值太大 (实际值: 24, 最大值: 10)
注意:数据库的NLS_CHARACTERSET 为AL32UTF8,即一个汉字占用三到四个字节。如果NLS_CHARACTERSET为ZHS16GBK,则一个字符占用两个字节。
如果串的长度小于或等于250(0x01~0xFA), Oracle 会使用1 个字节来表示长度。对于所有长度超过250 的串,都会在一个标志字节0xFE 后跟有两个字节来表示长度。因此,如果有一个包含“Hello World”的VARCHAR2(80),则在块中可能如图12.-1 所示
1.2: NCHAR类型
这是一个包含UNICODE格式数据的定长字符串。NCHAR字段最多可以存储2,000字节的信息。它的最大长度取决于国家字符集。另外查询时,如果字段是NCHAR类型,则需要如下书写
SELECT translated_description FROM product_descriptions
WHERE translated_name = N‘LCD Monitor 11/PM‘;
1.3 VARCHAR类型
不要使用VARCHAR数据类型。使用VARCHAR2数据类型。虽然VARCHAR数据类型目前是VARCHAR2的同义词,VARCHAR数据类型将计划被重新定义为一个单独的数据类型用于可变长度的字符串相比,具有不同的比较语义。
1.4: VARCHAR2类型
变长字符串,与CHAR类型不同,它不会使用空格填充至最大长度。VARCHAR2最多可以存储4,000字节的信息。
1.5: NVARCHAR2类型
这是一个包含UNICODE格式数据的变长字符串。 NVARCHAR2最多可以存储4,000字节的信息。
二. 数字类型
2.1 NUMBER类型
NUMBER(P,S)是最常见的数字类型,可以存放数据范围为10^130~10^126(不包含此值),需要1~22字节(BYTE)不等的存储空间。
P 是Precison的英文缩写,即精度缩写,表示有效数字的位数,最多不能超过38个有效数字
S是Scale的英文缩写,可以使用的范围为-84~127。Scale为正数时,表示从小数点到最低有效数字的位数,它为负数时,表示从最大有效数字到小数点的位数
下面是官方文档的示例
Actual Data |
Specified As |
Stored As |
123.89 |
NUMBER |
123.89 |
123.89 |
NUMBER(3) |
124 |
123.89 |
NUMBER(6,2) |
123.89 |
123.89 |
NUMBER(6,1) |
123.9 |
123.89 |
NUMBER(3) |
124 |
123.89 |
NUMBER(4,2) |
exceeds precision |
123.89 |
NUMBER(6,-2) |
100 |
.01234 |
NUMBER(4,5) |
.01234 |
.00012 |
NUMBER(4,5) |
.00012 |
.000127 |
NUMBER(4,5) |
.00013 |
.0000012 |
NUMBER(2,7) |
.0000012 |
.00000123 |
NUMBER(2,7) |
.0000012 |
1.2e-4 |
NUMBER(2,5) |
0.00012 |
1.2e-5 |
NUMBER(2,5) |
0.00001 |
2.2 INTEGER类型
INTEGER是NUMBER的子类型,它等同于NUMBER(38,0),用来存储整数。若插入、更新的数值有小数,则会被四舍五入。
例如:
CREATE TABLE TEST
(
ID INTEGER
)
查看表TEST的DDL定义如下所示
CREATE TABLE "SYS"."TEST"
( "ID" NUMBER(*,0)
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "SYSTEM" ;
INSERT INTO TEST
SELECT 12.34 FROM DUAL;
INSERT INTO TEST
SELECT 12.56 FROM DUAL;
SQL> SELECT * FROM TEST;
ID
----------
12
13
2.3 浮点数
浮点数可以有一个十进制数点任何地方从第一个到最后一个数字,或者可以在所有有没有小数点。指数可能(可选) 用于以下数量增加的范围 (例如, 1.777e-20)。刻度值不适用于浮点数字,因为可以显示在小数点后的位数的数量不受限制。
二进制浮点数不同数量的值由 Oracle 数据库内部存储的方式。使用小数精度数存储值。完全相同号码存储范围和数量由支持的精度内的所有文本。正是因为使用小数精度(数字 0 到 9) 表示文本存储文本。使用二进制精度 (数字 0 和 1) 存储二进制浮点数。这种存储方案不能代表所有确切地使用小数精度的值。频繁地,将值从十进制转换为二进制的精度时出现的错误时撤消值回从二进制转换为十进制精度。在字面 0.1 是一个这样的例子。
Oracle 数据库提供了专为浮点数的两种数值数据类型:
BINARY_FLOAT
BINARY_FLOAT 是 32 位、 单精度浮点数字数据类型。可以支持至少6位精度,每个 BINARY_FLOAT 的值需要 5 个字节,包括长度字节。
BINARY_DOUBLE
BINARY_DOUBLE 是为 64 位,双精度浮点数字数据类型。每个 BINARY_DOUBLE 的值需要 9 个字节,包括长度字节。
在数字的列中,浮点数有小数精度。在 BINARY_FLOAT 或 BINARY_DOUBLE 的列中,浮点数有二进制的精度。二进制浮点数支持的特殊值无穷大和 NaN (不是数字)。
您可以指定列在表 2-4 范围内的浮点数。"数字文本"中定义了用于指定浮点数的格式。
Table 2-3 Floating Point Number Limits
Value |
Binary-Float |
Binary-Double |
Maximum positive finite value |
3.40282E+38F |
1.79769313486231E+308 |
Minimum positive finite value |
1.17549E-38F |
2.22507485850720E-308 |
2.5 FLOAT类型
FLOAT类型也是NUMBER的子类型。
Float(n),数 n 指示位的精度,可以存储的值的数目。N 值的范围可以从 1 到 126。若要从二进制转换为十进制的精度,请将 n 乘以 0.30103。要从十进制转换为二进制的精度,请用 3.32193 乘小数精度。126 位二进制精度的最大值是大约相当于 38 位小数精度。
三. 日期类型
日期类型用于存储日期数据,但是并不是使用一般的格式(2012-08-08)直接存储到数据库的。
3.1 DATE类型
DATE是最常用的数据类型,日期数据类型存储日期和时间信息。虽然可以用字符或数字类型表示日期和时间信息,但是日期数据类型具有特殊关联的属性。为每个日期值,Oracle 存储以下信息: 世纪、 年、 月、 日期、 小时、 分钟和秒。一般占用7个字节的存储空间。
3.2 TIMESTAMP类型
这是一个7字节或12字节的定宽日期/时间数据类型。它与DATE数据类型不同,因为TIMESTAMP可以包含小数秒,带小数秒的TIMESTAMP在小数点右边最多可以保留9位
3.3 TIMESTAMP WITH TIME ZONE类型
这是TIMESTAMP类型的变种,它包含了时区偏移量的值
3.4 TIMESTAMP WITH LOCAL TIME ZONE类型
3.5 INTERVAL YEAR TO MOTH
3.6 INTERVAL DAY TO SECOND
四. LOB类型
内置的LOB数据类型包括BLOB、CLOB、NCLOB、BFILE(外部存储)的大型化和非结构化数据,如文本、图像、视屏、空间数据存储。BLOB、CLOB、NCLOB类型
4.1 CLOB 数据类型
它存储单字节和多字节字符数据。支持固定宽度和可变宽度的字符集。CLOB对象可以存储最多 (4 gigabytes-1) * (database block size) 大小的字符
4.2 NCLOB 数据类型
它存储UNICODE类型的数据,支持固定宽度和可变宽度的字符集,NCLOB对象可以存储最多(4 gigabytes-1) * (database block size)大小的文本数据。
4.3 BLOB 数据类型
它存储非结构化的二进制数据大对象,它可以被认为是没有字符集语义的比特流,一般是图像、声音、视频等文件。BLOB对象最多存储(4 gigabytes-1) * (database block size)的二进制数据。
4.4 BFILE 数据类型
二进制文件,存储在数据库外的系统文件,只读的,数据库会将该文件当二进制文件处理
五. RAW & LONG RAW类型
5.1 LONG类型
它存储变长字符串,最多达2G的字符数据(2GB是指2千兆字节, 而不是2千兆字符),与VARCHAR2 或CHAR 类型一样,存储在LONG 类型中的文本要进行字符集转换。ORACLE建议开发中使用CLOB替代LONG类型。支持LONG 列只是为了保证向后兼容性。CLOB类型比LONG类型的限制要少得多。 LONG类型的限制如下:
1.一个表中只有一列可以为LONG型。(Why?有些不明白)
2.LONG列不能定义为主键或唯一约束,
3.不能建立索引
4.LONG数据不能指定正则表达式。
5.函数或存储过程不能接受LONG数据类型的参数。
6.LONG列不能出现在WHERE子句或完整性约束(除了可能会出现NULL和NOT NULL约束)
官方文档描叙如下:
The use of LONG values is subject to these restrictions:
A table can contain only one LONG column.
You cannot create an object type with a LONG attribute.
LONG columns cannot appear in WHERE clauses or in integrity constraints (except that they can appear in NULL and NOT NULL constraints).
LONG columns cannot be indexed.
LONG data cannot be specified in regular expressions.
A stored function cannot return a LONG value.
You can declare a variable or argument of a PL/SQL program unit using the LONG datatype. However, you cannot then call the program unit from SQL.
Within a single SQL statement, all LONG columns, updated tables, and locked tables must be located on the same database.
LONG and LONG RAW columns cannot be used in distributed SQL statements and cannot be replicated.
If a table has both LONG and LOB columns, then you cannot bind more than 4000 bytes of data to both the LONG and LOB columns in the same SQL statement. However, you can bind more than 4000 bytes of data to either the LONG or the LOB column.
In addition, LONG columns cannot appear in these parts of SQL statements:
GROUP BY clauses, ORDER BY clauses, or CONNECT BY clauses or with the DISTINCT operator in SELECT statements
The UNIQUE operator of a SELECT statement
The column list of a CREATE CLUSTER statement
The CLUSTER clause of a CREATE MATERIALIZED VIEW statement
SQL built-in functions, expressions, or conditions
SELECT lists of queries containing GROUP BY clauses
SELECT lists of subqueries or queries combined by the UNION, INTERSECT, or MINUS set operators
SELECT lists of CREATE TABLE ... AS SELECT statements
ALTER TABLE ... MOVE statements
SELECT lists in subqueries in INSERT statements
5.2 LONG RAW 类型,能存储2GB 的原始二进制数据(不用进行字符集转换的数据)
5.3 RAW类型
用于存储二进制或字符类型数据,变长二进制数据类型,这说明采用这种数据类型存储的数据不会发生字符集转换。这种类型最多可以存储2,000字节的信息
六. ROWID & UROWID类型
在数据库中的每一行都有一个地址。然而,一些表行的地址不是物理或永久的,或者不是ORACLE数据库生成的。
例如,索引组织表行地址存储在索引的叶子,可以移动。
例如,外部表的ROWID(如通过网关访问DB2表)不是??标准的ORACLE的rowid。
ORACLE使用通用的ROWID(UROWIDs)的存储地址的索引组织表和外表。索引组织表有逻辑urowids的,和国外表的外urowids,。UROWID这两种类型的存储在ROWID伪(堆组织的表的物理行id)。
创建基于逻辑的rowid在表中的主键。逻辑的rowid不会改变,只要主键不改变。索引组织表的ROWID伪UROWID数据类型。你可以访问这个伪列,你会堆组织表的ROWID伪(即使用一个SELECT ...ROWID语句)。如果你想存储的rowid索引组织表,那么你就可以定义一列的表型UROWID到列检索值的ROWID伪。
以上是关于Oracle数据类型及存储方式的主要内容,如果未能解决你的问题,请参考以下文章