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 Code
  1. SQL> show parameter nls_length_semantics;
  2.  
  3. NAME                   TYPE           VALUE
  4. ------------------   ----------- -----------------
  5.  
  6. nls_length_semantics   string          BYTE
  7.  
  8. eg:
  9.  
  10. CREATE TABLE TEST
  11.  
  12. (
  13.  
  14. NAME_OLD CHAR(10),
  15.  
  16. NAME_NEW CHAR(10 CHAR)
  17.  
  18. )
  19.  
  20. INSERT INTO TEST
  21.  
  22. ( NAME_OLD, NAME_NEW)
  23.  
  24. SELECT ‘ABCDEFGHIJ‘ , ‘你清除字节与字符‘ FROM DUAL;
  25.  
  26. COMMIT;
  27.  
  28. INSERT INTO TEST
  29.  
  30. ( NAME_OLD, NAME_NEW)
  31.  
  32. SELECT ‘你清除字节与字符‘ , ‘ABCDEFGHIJ‘ FROM DUAL;
  33.  
  34. 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数据类型及存储方式的主要内容,如果未能解决你的问题,请参考以下文章

oracle 存储过程 变量的声明和赋值的3种方式

datagrips oracle编写存储过程

跪求一个超难的ORACLE数据纵向存储转成横向查询输出

Oracle基本数据类型

mysql存储引擎和数据类型

Oracle字段类型及存储