数据库中的每一个表都被一个模式(或用户)所拥有,因此表是一种典型的模式对象。在创建数据表时,Oracle 将在一个指定的表空间中为其分配存储空间。最初创建的表时一个空的逻辑存储结构,其中不包含任何数据记录。
一、数据表的逻辑结构
表是最常见的一种组织数据的方式,一张表一般都具有多个列(即多个字段)。每个字段都具有特定的属性,包括字段名、数据类型、字段长度、约束、默认值等,这些属性在创建表的时被确定。
Oracle 常用的5种数据类型:
1、字符类型
字符类型用于什么包含字母、数字数据的字段。对字符数据类型再细分可包括定长字符串和变长字符串两种,分别对应着 char 数据类型和 varchar 数据类型。
CHAR 数据类型,用于存储固定长度的字符串。一旦定义了 char 类型的列,该列就会一直保持声明时所规定的长度大小。当为该列的某个单元格(行与列的交叉处就是单元格)赋予长度较短的数值后,空余部分 Oracle 会用空格自动填充;如果字段保存的字符长度大于规定的长度,则 Oracle 会产生错误信息。char 类型的长度范围为 1~ 2000字节。
VarChar2 类型 : varchar2 用于存储变长的字符串。将字段定义为 varchar2 数据类型时,该字段的长度将根据实际字符数据的长度自动调整(即如果该列的字符串长度小于定义时的长度,系统不会使用空格填充,而是保留实际的字符串长度)。因此,在大多数情况下,都会使用 varchar2 替换 char 数据类型。
2、数值类型
数值数据类型的字段用于存储带符号的整数或浮点数。Oracle 中的 number 数据类型具有精度(precision)和范围(scale)。精度指定所有数字位的个数,范围值定小数的位数,这两个参数都是可选的。如果插入的数据超过指定的位数,Oracle 将自动进行四舍五入。
3、日期时间类型
Oracle 提供的日期时间数据类型时 DATE,它可以存储日期和时间的组合数据。用DATE 数据类型存储日期时间比使用字符数据类型进行存储更简单,并且可以借助于 Oracle 提供的日期时间函数方便处理数据。
在 Oracle 中,可以使用不同的方法建立日期值。最常用的获取日期的方法是通过 sysdate 函数,调用该函数可以获取当前系统的日期值。还可以使用 To_DATE 函数将数值或字符串转换为 DATE 类型。 Oracle 默认的日期和时间格式由初始化参数 NLS_DATE_FORMAT 指定,一般为 DD-MM-YY。
4、LOB类型
Lob 数据类型用于大型的、未被结构化的数据,例如二进制文件、图片文件和其他类型的外部文件。LOB 类型的数据可以存储在数据库内部,也可以将数据存储在外部文件中,而将指向数据的指针存储在数据库中。LOB 数据类型分为 BLOB、CLOB 和 BFILE 数据类型。
BLOB 类型:blob类型用于存储二进制对象。典型的 blob 可以包括图像、音频文件、视频文件等。在 blob 类型的字段中能够存储最大为 128MB的二进制对象。
CLOB 类型: clob 类型用于存放字符格式的大型对象,CLOB 类型的字段能够存储最大为 128MB 的对象。Oracle 首先把数据转换成Unicode格式的编码,然后再将它存储在数据库中。
BFILE 类型:bfile 类型用于存储二进制格式的文件;在 bfile 类型的字段中可以将最大为128MB 的二进制文件作为操作系统文件存储在数据库外部,文件的大小不能超过操作系统的限制;bfile 类型的字段中仅保存二进制文件的指针,并且 bfile 字段是只读的,不能修改。
5、RowID 数据类型
RowID 数据类型被称为 “伪列类型”,用于在 Oracle 内部保存表中的每条记录的物理地址。在 Oracle 内部通过 rowid 来定位所需记录的。由于 rowID 实际上保存的时数据记录的物理地址,所以通过 rowid 来访问数据记录可以获得最快的访问速度。为了便于使用,Oracle 自动为每一个表建立一个名称为 rowID 的字段,可以对这个字段进行查询、更新和删除等操作,设置利用 rowID 来访问表中的记录以获取最快的操作速度。
注意:由于 rowid 字段是隐式的,用户检索表时不会看到该字段,因此,如果要使用 rowid 字段,则必须显示地指定其名称。
二、创建数据表
创建表通常使用 create table 语句。如果用户在自己的模式中创建一个表,则用户必须具有 create table 系统权限。如果要在其他用户模式中创建表,则必须具有 create any tables 的系统权限。此外,用户还必须在指定的表空间中设置一定的配额存储空间。
创建表应该包含哪些列并且指定这些列的数据类型,而这些内容最好在对用户需求分析的基础上进行确定。
语法格式:
create table table_name( 字段名1 数据类型, 字段名2 数据类型 );
注意:1、如果用户要在其他模式中创建表,则必须在表名前加上某个模式的名称。
2、在create table 语句中可以使用嵌套子查询,基于已经存在的表或视图来创建新表,不需要为新表定义字段。
例:
SQL > create table students_2 as select * from students;
三、数据表的特性
在 Oracle 中创建表时,表的特性将决定系统如何创建表、如何在磁盘上存储表,以及表创建后使用时的最终执行方式等。
1、存储参数
当用户在 Oracle 中创建表时,Oracle 允许用户指定该表如何使用磁盘上的存储空间。如果仅为表指定了表空间,而没有设置存储参数,则该表将采用其所属表空间的默认的存储参数。然而,表空间的默认存储参数不一定对表空间的每一个表都适用,因此,当表所需要的存储参数与表空间的默认存储参数不匹配时,需要用户在创建表时显式指定存储参数以体寒表空间的默认存储参数。
在创建表时,可以通过使用 storage 子句来设置存储参数,这样可以控制表中盘区的分配管理方式。对于本地化管理的表空间而言,如果指定盘区的管理方式为 autoallocate(自动化管理) ,则可以在 storage 子句中指定 initial、next 和 minextents 这3个存储参数,Oracle 将根据这3个存储参数的值为表分配的数据段初始化盘区大小,以后盘区的分配将由 Oracle 自动管理。如果指定的盘区管理方式为 uniform(等同大小管理),这时不能为表指定任何 storage 子句,盘区的大小将是统一大小。
参数 next 用于指定为存储表中的数据分配的第二个盘区大小。该参数在字典管理的表空间中起作用,而在本地化管理的表空间中不再起作用,因为随后分配的盘区将由 Oracle 自动决定其大小。参数 minextents 用于指定允许为表中的数据所分配的最小盘区数目,同样在本地化管理的表空间中该参数也不再起作用。因此,在存储参数中,主要是设置 inital 参数。该参数用于为表指定分配的第一个盘区大小,以 KB 和 MB 为单位。当为已知大小的数据建立表时,可以将 initial 设置为一个可以荣脑所有数据的数值,这样可以将表中所有的数据存储在一个盘区从而避免产生碎片。
例:
SQL > select initial_extent from user_tables where table_name = 'students'
在user_tables 数据字典表中查询表 students 的第一个盘区的大小。
2、数据块管理参数
对于一般不带有LOB 类型的数据表而言,一个数据块可以存放表的多行记录,用户可以设置的数据块管理参数主要分为以下两类:
1、Pctfree 和 pctused
这两个参数用于控制数据块中空闲空间的使用方法。对于本地化管理的表空间而言,如果使用 segment space maxagement 子句设置段的管理方式为 auto,则 Oracle 会对数据库的空闲空间进行自动管理。对于这种情况,不需要用户设置数据块管理参数 pctfree 和 pctused。
如果表空间的段管理方式 segment space maxagement manual(手动管理),则用户可以通过设置pctfree 和 pctused 参数对数据块中的空闲空间手动管理。其中,pctfree 用于指定数据库必须保留的最小空闲空间比例,当数据块达到 pctfree 参数的限制后,该数据块将被标记为不可用,默认值为10。如果 pctfree 参数值设置德过高,则良妃磁盘空间;如果pctfree 设置得太低,可能会导致由于一个数据块小到无法容纳一行记录而产生迁移记录和链接记录。
参数 pctused 用于设置数据块是否可用的界限,为了使数据块能够被再次使用,已经占用的存储空间必须低于 pctused 设置的比例。
设置数据块的pctfree 和 pctused 时,用户需要根据数据库的具体应用情况来决定。下面是设置参数的几种情况:
(1)在实际中,当使用 update 操作较多,并且更新操作会增加记录的大小时,可以将 pctfree 值设置得大一点儿,这样当记录变大时,记录仍然能够保存在原数据块中;而将pctused 值设置得比较小,这样在频繁地进行更新操作时,能够减少由于数据块在可用与不可用状态之间反复切换而造成的系统开销。推荐设置 pctfree 为 20,而 pctused 为 40。
(2)在实际中,当使用 insert 和 delete 操作较多,并且 update 操作不会增加记录的大小时,可以将 pctfree 参数设置得比较小,因为大部分更新操作不会增加记录的大小;而 pctused 参数设置得比较大,以便尽快重新利用被 delete 操作释放的存储空间。推荐设置参数 pctfree 为 5,而 pctused 为60。
2、initrans 参数
该参数用于指定一个数据块所允许的并发事务数目。当一个事务访问表中的一个数据块时,该事务会在数据块的头部保存一个条目,以标识该事务正在使用这个数据块。当该事务结束时,它所对应的条目将被删除。
在创建表时,Oracle 会在表的每个数据块头部分分配可以存储 initrans 个事务条目的空间,这部分空间是永久的,只能用于存储事务条目。当数据块的头部空间已经存储了 initrans 个事务条目后,如果还有其他事务要访问这个数据块,Oracle 将在数据块的空闲空间中为事务分配空间,这部分空间是动态的。当事务结束后,这部分存储空间将被回收一存储其他数据。能够访问一个数据块的事务总数由 maxtrans 参数决定。在 11g 中,对于当个数据块而言,Oracle 默认最大支持255个并发事务。
可以在 user_tables 数据字典中查询某个表的 ini_trans 和 max_trans 参数值。
例:
SQL > select ini_trans,max_trans from user_tables where table_name = 'students'
3、重做日志参数
重做日志记录了数据库中数据的该表情况,这样,如果发生故障导致数据不能从内存中写入到数据文件中时,就可以从重做日志文件中获取被操作的数据。这样就可以防止数据丢失,从而提高表中数据的可靠性。
当使用 create table 语句创建表时,如果使用了nologging 子句,则对该表进行 DDL 操作(如create、alter、drop等)就不会记录到日志中,但对该表进行 DML 操作(如 insert、update、delete等)时,系统仍然会产生重做日志记录。在创建表时,默认情况下使用 Logging 子句,这样对该表的所有操作(包括创建、删除、重命名等操作)都会被记录到重做日志中。
在决定是否使用了 nologging 子句时,用户必须综合考虑获取的收益和风险。使用 nologging 子句时,可以节省重做日志文件的存储空间,并减少创建表所需要的时间。但如果没有在重做日志文件中记录对表的操作,可能会无法用数据库恢复操作来恢复丢失的数据。
4、缓存参数
当在 Oracle 中执行全表搜索时,读入缓存中的数据块将会存储在 LRU 列表的最近最少使用的一端,这意味着如果进行查询操作,并且必须向缓存中存储数据时,就会将刚读入的数据块换出缓存。
在建立表时,可以使用 cache 子句改变这种行为,使得当在使用 cache 子句建立的表中执行全表搜索时,将读入的数据块放置到 LRU 中最近最常使用的一端。这样,数据库缓存中利用 LRU 算法对缓存块进行换入、换出调度时,就不会将属于这个表的数据库立即换出,从而提高了针对该表的查询效率。
在创建表时默认使用 nocache 子句。对于比较小且经常查询的表,用户在创建表时指定 cache 子句,以便利用系统缓存来提高对该表的查询执行效率。