暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 19C入门到精通之创建数据表

ITPro进化论 2023-12-25
190

1. 数据表概述

数据表(通常简称表)是Oracle数据库中主要的数据存储容器,表中的数据被组织成行和列。表中的每个列均有一个名称,并且每个列都具有一个指定的数据类型和大小,如VARCHAR(30)、TIMESTAMP(6)或NUMBER(12)。

数据表的逻辑结构是一个二维的平面表,即表由纵向的标记列和横向的标记行两部分组成。表通过行和列来组织数据。通常称表中的一行为一条记录,表中的一列为一个属性列。一条记录描述一个实体,一个属性列描述实体的一个属性,如员工有员工编号、员工姓名、员工岗位等属性,学生有学生编号、姓名、所在学校等属性。每个列都具有列名、列数据类型、列数据长度,可能还有约束条件、默认值等,这些内容在创建表时即被确定。

表一般指的是关系表,也可以生成对象表或临时表。其中,对象表是通过用户定义的数据类型生成的,临时表用于存储专用于某个事务或者会话的临时数据。

2. 创建数据表

数据库中的每个表都被某个模式(或用户)所拥有,因此表是一种典型的模式对象。在创建数据表时,Oracle将在一个指定的表空间中为其分配存储空间。最初创建的表是一个空的逻辑存储结构,其中不包含任何数据记录。

2.1. 数据表的逻辑结构

表是最常见的一种组织数据的方式,每张表一般都具有多个列(即多个字段)。每个字段都具有特定的属性,包括字段名、数据类型、字段长度、约束、默认值等,这些属性在创建表时被确定。

Oracle提供了多种内置的列的数据类型,常用的有字符类型、数值类型、日期和时间类型、LOB类型与ROWID类型。除了这些类型,用户还可以自定义数据类型。

2.1.1. 字符数据类型

字符数据类型用于声明包含字母、数字数据的字段。对字符数据类型再进行细分,可分为定长字符串和变长字符串两种,它们分别对应CHAR数据类型和VARCHAR2数据类型。

  • CHAR数据类型:用于存储固定长度的字符串。
  • VARCHAR2数据类型:用于存储变长的字符串。

2.1.2. 数值数据类型

类型具有精度(PRECISION)和范围(SCALE)两个参数。Oracle中的NUMBER数据类型具有精度(PRECISION)和范围(SCALE)两个参数。精度(PRECISION)指定所有数字位的个数,范围(SCALE)指定小数的位数,这两个参数都是可选的。如果插入字段的数据超过指定的位数,Oracle将自动进行四舍五入。

2.1.3. 日期和时间数据类型

Oracle提供的日期和时间数据类型是DATE,它可以存储日期和时间的组合数据。用DATE数据类型存储日期和时间比使用字符数据类型进行存储更简单,并且可以借助Oracle提供的日期时间函数方便地处理数据。

Oracle中使用SYSDATE函数可以获取当前系统的日期值。可以使用TO_DATE函数将数值或字符串转换为DATE类型。

2.1.4. LOB数据类型

LOB数据类型用于大型的、未被结构化的数据,如二进制文件、图片文件和其他类型的外部文件。LOB类型的数据可以被直接存储在数据库内部,也可以将数据存储在外部文件中,而将指向数据的指针存储在数据库中。LOB数据类型分为BLOB、CLOB和BFILE共3种。

  • BLOB类型:用于存储二进制对象。典型的BLOB存储对象可以包括图像、音频文件、视频文件等。在BLOB类型的字段中能够存储最大为128 MB的二进制对象。
  • CLOB类型:用于存储字符格式的大型对象,CLOB类型的字段能够存储最大为128 MB的对象。Oracle首先把数据转换成Unicode格式的编码,然后将它存储在数据库中。
  • BFILE类型:用于存储二进制格式的文件。在BFILE类型的字段中可以将最大为128 MB的二进制文件作为操作系统文件存储在数据库外部,文件的大小不能超过操作系统的限制;BFILE类型的字段中仅保存二进制文件的指针,并且BFILE字段是只读的,不能通过数据库对其中的数据进行修改。

2.1.5. ROWID数据类型

ROWID数据类型被称为“伪列类型”,用于在Oracle内部保存表中的每条记录的物理地址。在Oracle内部通过ROWID来定位所需记录。

注意:由于ROWID字段是隐式的,用户检索表时不会看到该字段。因此,如果要使用ROWID字段,则必须显式地指定其名称。

2.2. 创建数据表

创建表通常使用CREATE TABLE语句。如果用户在自己的模式中创建一个表,则用户必须具有CREATE TABLE系统权限;如果要在其他用户模式中创建表,则必须具有CREATE ANY TABLE的系统权限。

创建一个学生档案信息表students,该表包括学号、姓名、性别、年龄、系别编号、班级编号和建档日期等信息,代码如下:

create table students(
stuno number(10not null,      --学号
stuname varchar2(8),            --姓名
sex char(2),                    --性别
age int,                        --年龄
departno varchar2(2not null,  --系别编号
classno varchar2(4not null,   --班级编号
regdate date default sysdate    --建档日期
);

如果用户要在其他模式中创建表,则必须在表名称前加上某个模式的名称,例如:

--用户system在scott模式下创建students表
create table scott.students(…);

可以在CREATE TABLE语句中使用嵌套子查询,基于已经存在的表或视图来创建新表,而不需要为新表定义字段。在子查询中也可以引用一个或多个表(或视图),查询结果集中包含的字段即为新表中定义的字段,并且查询到的记录也会被添加到新表中。

使用CREATE TABLE AS SELECT语句创建students表的一个副本,代码如下:

create table students_2 as select * from students;

当使用CREATE TABLE AS SELECT语句创建表时,Oracle将通过从students表中复制列来建立表。在创建表后,Oracle就会使用从SELECT语句中返回的行来填充新表。

3. 数据表的特性

在Oracle中创建表时,表的特性将决定系统如何创建表、如何在磁盘上存储表,以及表创建后使用何种最终执行方式等。常用的表的4个特性如下:

3.1. 存储参数

当用户在Oracle中创建表时,Oracle允许用户指定该表如何使用磁盘上的存储空间。如果仅为表指定了表空间,而没有设置存储参数,则该表将采用其所属表空间的默认存储参数。然而,表空间的默认存储参数不一定对表空间中的每一个表都适用,因此,当表所需要的存储参数与表空间的默认存储参数不匹配时,需要用户在创建表时显式指定存储参数以替换表空间的默认存储参数。

在创建表时,可以通过使用STORAGE子句来设置存储参数,这样可以控制表中盘区的分配管理方式。对于本地化管理的表空间而言,如果指定盘区的管理方式为AUTOALLOCATE(即自动化管理),则可以在STORAGE子句中指定INITIAL、NEXT和MINEXTENTS 3个存储参数,Oracle将根据这3个存储参数的值为表分配数据段初始化盘区大小,以后盘区的分配将由Oracle自动管理。如果指定的盘区管理方式为UNIFORM(即等同大小管理),这时不能为表指定任何STORAGE子句,盘区的大小将是统一大小。

参数NEXT用于指定为存储表中的数据分配的第二个盘区大小。该参数在字典管理的表空间中起作用,而在本地化管理的表空间中不再起作用,因为随后分配的盘区将由Oracle自动决定其大小。参数MINEXTENTS用于指定允许为表中的数据所分配的最小盘区数目,同样,在本地化管理的表空间中该参数也不再起作用。因此,在存储参数中,主要是设置INITIAL参数。该参数用于为表指定分配的第一个盘区大小,以KB或MB为单位。当为已知大小的数据建立表时,可以将INITIAL设置为一个能容纳所有数据的数值,这样可以将表中所有数据存储在一个盘区以避免产生碎片。

创建一个用于存储学生档案信息的students_3数据表(该表的结构与前面的students表相同),并通过STORAGE子句中的INITIAL存储参数为该表分配第一个盘区的大小,代码如下:

create table students_3(
stuno number(10not null,      --学号
stuname varchar2(8),            --姓名
sex char(2),                    --性别
age int,                        --年龄
departno varchar2(2not null,  --系别编号
classno varchar2(4not null,   --班级编号
regdate date default sysdate    --建档日期
)tablespace tbs_test_1          --表空间
storage(initial 256k);          --指定为该表分配的第一个盘区的大小

--在user_tables数据字典表中查询表students_3的第一个盘区的大小
select initial_extent from user_tables where table_name = 'STUDENTS_3';

3.2. 数据块管理参数

对于一般不带有LOB类型的数据表而言,一个数据块可以存储表的多行记录,用户可以设置的数据块管理参数主要分为以下两类。

①PCTFREE和PCTUSED参数

PCTFREE和PCTUSED两个参数用于控制数据块中空闲空间的使用方法。

对于本地化管理的表空间而言,如果使用SEGMENT SPACE MANAGEMENT子句设置段的管理方式为AUTO(自动),则Oracle会对数据库的空闲空间进行自动管理。对于这种情况,不需要用户设置数据块管理参数PCTFREE和PCTUSED。

如果表空间的段管理方式为SEGMENT SPACE MANAGEMENT MANUAL(手动管理),则用户可以通过设置PCTFREE与PCTUSED参数对数据块中的空闲空间手动管理。其中,PCTFREE用于指定数据库中必须保留的最小空闲空间比例,当数据块达到PCTFREE参数的限制后,该数据块将被标记为不可用,默认值为10。例如,如果在CREATE TABLE语句中指定PCTFREE为30,则说明对于该表的数据段,系统将会保留30%的空闲空间,这些空闲空间将用于保存更新记录时增加的数据。很显然,PCTFREE参数值越小,为现有数据行更新所预留的空间就越少。如果PCTFREE参数值设置得过高,则浪费磁盘空间;如果PCTFREE参数值设置得太低,则可能会导致由于一个数据块小到无法容纳一行记录而产生迁移记录和链接记录。

参数PCTUSED用于设置数据块是否可用的界限。换言之,为了使数据块能够被再次使用,已经占用的存储空间必须低于PCTUSED设置的比例。

为表设置PCTFREE与PCTUSED参数时,PCTFREE和PCTUSED两个参数值的和必须等于或小于100。一般而言,两个参数的和与100相差越大,存储效率就越高。

设置数据块的PCTFREE和PCTUSED时,用户需要根据数据库的具体应用情况来做出决定。下面是设置PCTUSED和PCTFREE两个参数的几种情况:

  • 在实际应用中,当使用UPDATE操作较多,并且更新操作会增加记录的大小时,可以将PCTFREE参数值设置得大一些,这样当记录变大时,记录仍然能够保存在原数据块中;而如果将PCTUSED参数值设置得比较小,这样在频繁地进行更新操作时,能够减少由于数据块在可用与不可用状态之间反复切换而造成的系统开销。推荐设置PCTFREE为20,而PCTUSED为40。
  • 在实际应用中,当使用INSERT和DELETE操作较多,并且UPDATE操作不会增加记录的大小时,可以将PCTFREE参数值设置得比较小,因为大部分更新操作不会增加记录的大小;而将PCTUSED参数值设置得比较大,以便尽快重新利用被DELETE操作释放的存储空间。推荐设置参数值PCTFREE为5,而PCTUSED为60。

在CREATE TABLE语句中,可以通过PCTFREE和PCTUSED子句来设置相应的参数。

创建students_4数据表,并设置其PCTFREE和PCTUSED的参数值分别为20和40,代码如下:

create table students_4(
stuno number(10not null,      --学号
stuname varchar2(8),            --姓名
sex char(2),                    --性别
age int,                        --年龄
departno varchar2(2not null,  --系别编号
classno varchar2(4not null,   --班级编号
regdate date default sysdate    --建档日期
)tablespace tbs_test_1          --表空间
storage(initial 256k)           --该表分配第一个盘区的大小
pctfree 20                      --数据块管理参数
pctused 40;                     --数据块管理参数

用户如果要查看表students_4的PCTFREE和PCTUSED参数设置情况,可以通过查看user_tables数据字典视图来实现。

②INITRANS参数

INITRANS参数用于指定一个数据块所允许的并发事务数目。当一个事务访问表中的一个数据块时,该事务会在数据块的头部保存一个条目,以标识该事务正在使用这个数据块。当该事务结束时,它所对应的条目将被删除。

在创建表时,Oracle会在表的每个数据块头部分配可以存储INITRANS个事务条目的空间,这部分空间是永久的,只能用于存储事务条目。当数据块的头部空间已经存储了INITRANS个事务条目后,如果还有其他事务要访问这个数据块,Oracle将在数据块的空闲空间中为事务分配空间,这部分空间是动态的。当事务结束后,这部分存储空间将被回收以存储其他数据。能够访问一个数据块的事务总数由MAXTRANS参数决定,在Oracle中,对于单个数据块而言,Oracle默认最大支持255个并发事务。但实际上,MAXTRANS参数已经被废弃。

创建students_5表,并指定在数据块头部存储10个事务条目,代码如下:

create table students_5(
stuno number(10not null,      --学号
stuname varchar2(8),            --姓名
sex char(2),                    --性别
age int,                        --年龄
departno varchar2(2not null,  --系别编号
classno varchar2(4not null,   --班级编号
regdate date default sysdate    --建档日期
)tablespace tbs_test_1
storage(initial 256k)
pctfree 20
pctused 40
initrans 10;   --数据块管理参数,10个事务条目

若要了解students_5表中的INITRANS和MAXTRANS参数的设置情况,可以通过查询数据字典user_tables来实现;

select ini_trans,max_trans from user_tables where table_name = 'STUDENTS_5';

由于每张表的应用特性不同,所以应当为每张表分别设置不同的INITRANS参数。在设置INITRANS参数时,如果设置的INITRANS参数值较大,则事务条目将占用过多的存储空间,因而会减少用来存储实际数据的存储空间。只有当一个表有较多的事务同时访问时,才应当为其设置较高的INITRANS参数值。

3.3. 重做日志参数

重做日志记录了数据库中数据的变化情况。如果发生故障导致数据不能从内存中被写入数据文件中时,就可以从重做日志中获取被操作的数据。这样就可以防止数据丢失,从而提高表中数据的可靠性。

当使用CREATE TABLE语句创建表时,如果使用NOLOGGING子句,则对该表的创建、删除、修改等操作(即DDL操作)不会被记录到日志中,但对该表进行DML操作(如INSERT、UPDATE、DELETE等)时,系统仍然会产生重做日志记录。在创建表时,默认情况下使用LOGGING子句,这样对该表的所有操作(包括创建、删除、重命名等操作)都会被记录到重做日志中。

在决定是否使用NOLOGGING子句时,用户必须综合考虑所产生的收益和风险。使用NOLOGGING子句时,可以节省重做日志文件的存储空间,并减少创建表所需要的时间。但如果没有在重做日志文件中记录对表的操作,可能会无法用数据库恢复操作来恢复丢失的数据。

创建students_6表,并且在创建该表时使用NOLOGGING子句,使用户对该表的创建、删除、修改等操作不被记录到重做日志文件中,代码如下:

create table students_6(
stuno number(10not null,      --学号
stuname varchar2(8),            --姓名
sex char(2),                    --性别
age int,                        --年龄
departno varchar2(2not null,  --系别编号
classno varchar2(4not null,   --班级编号
regdate date default sysdate    --建档日期
)tablespace tbs_test_1
storage(initial 256k)
pctfree 20
pctused 40
initrans 10
nologging;   --对DDL操作不产生日志

3.4. 缓存参数

当在Oracle中执行全表搜索时,读入缓存中的数据块将会存储在LRU列表最近最少使用的一端。这意味着如果进行查询操作,并且必须向缓存中存储数据时,就会将刚读入的数据块换出缓存。

在建立表时,可以使用CACHE子句改变这种行为,使得在使用CACHE子句建立的表中执行全表搜索时,将读入的数据块放置到LRU中最近最常用的一端。这样,当数据库缓存利用LRU算法对缓存块进行换入、换出调度时,就不会将属于这张表的数据块立即换出,从而提高了针对该表的查询效率。

在创建表时默认使用NOCACHE子句。对于比较小且又经常查询的表,用户在创建表时指定CACHE子句,以便利用系统缓存来提高对该表的查询执行效率。

在user_table数据字典中查询students_6表是否启用了缓存功能,代码如下:

select table_name,cache from user_tables where table_name = 'STUDENTS_6';

今天的文章就到这里,如果对你有用,记得点个【赞】【在看】,感谢阅读~

文章转载自ITPro进化论,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论