表一般指的是一个关系表,也可以生成对象表以及临时表。齐总,对象表是通过用户定义的数据类型生成的,临时表用于存储专用于某个事务或会话的临时数据
字符类型:
定长:char (1-2000字节)
变长:varchar2
数值类型: number(precision,scale)
日期时间类型:
date,默认的日期和时间格式由初始化参数nls_date_format指定,一般为DD-MM-YY
LOB类型:
用于大型的、未被结构化的数据,如二进制、图片和其他类型的外部文件。LOB类型的数据可以直接存储在数据库,也可以将数据存储在外部文件中,而将指向数据的指针存储在数据库中。LOB分为BLOB,CLOB,BFILE
BLOB:用于存储二进制对象。典型的BLOB可以包括对象、音频文件、视频文件等。在BLOB类型中能够存储最大为128MB的二进制对象
CLOB:用于存储字符格式的大型对象,CLOB类型的字段能够存储最大为128MB对象。Oracle首先把数据转换成Unicode,然后再将它存储在数据库中
BFILE:用于存储二进制格式的文件;在BFILE可以将最大为128MB的二进制文件作为操作系统文件存储在数据库外部,文件的大小不能超过操作系统的限制;BFILE字段中仅保存二进制文件的指针,并且BFILE字段是只读的,不能通过数据库对其中的数据进行修改
ROWID类型:
“伪列类型”,用于Oracle内部保存表中的每条记录的物理地址。在Oracle内部通过ROWID来定位所需的记录。
由于实际上ROWID保存的是数据记录的物理地址,所以通过ROWID来访问数据记录可以获得最快的访问速度。为了便于使用,Oracle自动为每一个表建立一个名称为ROWID字段,可以对这个字段进行查询、更新和删除等操作,设置利用ROWID来访问表中的记录以获得最快的操作速度
创建一个数据表
如果用户在自己的模式下,创建必须有create table系统权限,如果是在其他用户模式中创建表,那么必须具有create any table 系统权限
如:创建一个学生档案信息表students,该表包括了学号、姓名、性别、年龄、系别编号、班级编号、和建档日期等信息:
create table students(
stuno number(10) not null,
stuname varchar2(8),
sext char(2),
age int,
departno varchar2(2) not null,
classno varchar2(4) not null,
regdate date default sysdate);
注意:如果用户在其他模式中创建表,在表名前加上某个模式的名称
还可以,基于已经存在的表或视图来创建新表
如:使用create table ... as select 语句创建students 表的一个副本:
create table students_2 as
select * from students;
这样创建表之后,Oracle将通过从students中复制列(包括数据)来建立表
数据表的特性
在Oracle中创建表后,表的特性将决定系统如何创建表、如何在磁盘上存储表,以及表创建后使用时的最终执行方式
接下来,详解表中常用的4个参数:
A--存储参数(storage)
当用户在Oracle中创建表时,Oracle允许用户指定该表如何使用磁盘上的存储空间。如果没有指定存储参数,则该表将采用其所属表空间的默认存储参数。
若要设置,对于本地化管理的表空间而言,如果指定盘区的管理方式为autoallocate(另一个是uniform),则可以指定initial,next(数据分配的第二个盘区的大小,local 中不起作用,dictionary方可),minextents(允许表中的数据所分配的最小盘区数目,local中不起作用,dictionary方可)
initial:第一个盘区大小,以KB或MB为单位
如:创建一个用于存储学生档案信息的students_3数据表(该表的结构与上面的students表的结构相同),并通过storage子句中的initial存储参数为该表分配第一个盘区的大小为256kB:
create table students_3(
stuno number(10) not null,
stuname varchar2(8),
sex char(2),
age int,
departno varchar2(2) not null,
classno varchar2(4) not null,
regdate date default sysdate)
tablespace play storage (initial 256k)
/
如果要查询数据表的存储参数情况,可以使用DD--user_tables(initial_extent)
B--数据块管理参数
对于一般不带有LOB类型的数据表而言,一个数据块可以存放表的多行记录,用户可以设置的数据块管理参数有:
(对于segment space manage=auto,不用设置下面的参数;为manual时需要设置)
PCTFREE 和PCTUSED
pctfree用于指定数据库必须保留的最小空间比例,当数据块达到PCTFREE参数的限制后,该数据块将被标记为不可用,默认值为10
pctused:用于设置数据块是否可用的界限。也就是说,为了使数据块能够被再次使用,已经占用的存储空间必须低于PCTUSED设置的比例
注意:一般这两个参数的和必须等于或小于100,两个参数和与100相差越大,存储效率就越高
一般在实际的应用中
当使用UPDATE操作较多,可以设置pctfree较大些,而pctused较小些,推荐pctfree20 pctused40
当使用的INSERT操作较多,可以设置pctfree较小些,而pctused较大些,推荐pctfree5 pctused60
如:创建students_4数据表,并设置其pctfree和pctused为20和40:
create table studnets_4(
stuno number(10) not null,
stuname varchar2(8),
sex char(2),
age int,
departno varchar2(2) not null,
classno varchar2(4) not null,
regdate date default sysdate)
tablespace play storage(initial 256k)
pctfree 20 pctused 40
/
C--INITRANS参数(默认是1)
该参数用于指定一个数据块所允许的并发事务数目。当一个事务访问表的一个数据块时,该事务会在数据块的头部保存一个条目,以标识该事务正在使用这个数据块。当该事务结束时,它所对应的条目将被删除。对于单个数据块而言,能够访问访问一个数据块的事务总数是由MAXTRANS参数决定的,而Oracle 11g 默认最大支持255并发事务。但实际上,MAXTRANS已经被废弃
如:创建students_5表,并指定在数据块头部存放10个事务条目:
create table students_5(
stuno number(10) not null,
stname varchar2(8),
sext char(2),
age int,
departno varchar2(2) not null,
classno varchar2(4) not null,
regdate date default sysdate)
tablespace play storage(initial 256k)
pctfree 20 pctused 40 initrans 10;
可以使用DD--user_tables(ini_trans,max_trans)
由于每个表的应用特性不同,所以应当为各个表分别设置不同的INITRANS,但不宜太大
D--重做日志参数
默认情况下,在创建表时,是使用LOGGING子句的。在考虑是否采用NOLOGGING子句时,用户必须综合考虑所获取的收益和风险。使用NOLOGGING子句时,可以节省重做日志文件的存储空间,并减少创建表所需要的时间。但如果没有在重做日志文件中记录对表的操作,可能无法用数据库恢复操作来恢复丢失的数据。
如:创建students_6,并且在创建该表时使用nologging子句,使用户对该表的创建、删除、修改(DDL)等操作不被记录到重做日志文件中:
create table students_6(
stuno number(10) not null,
stuname varchar2(8),
sex char(2),
age int,
departno varchar2(2) not null,
classno varchar2(4) not null,
regdate date default sysdate)
tablespace play storage(initial 256k)
pctfree 20 pctused 40 initrans 10 nologging
/
E--缓存参数
当在Oracle中执行全表搜索时,读入缓存中的数据块将会存储在LRU列表的最近最少使用的一端。也就是说,如果进行查询操作,并且必须向缓存中存储数据时,就会将刚刚读入的数据块换出缓存
在建立表时,可以使用CACHE子句改变这种行为,使得当在使用CACHE子句建立的表中执行全表搜索时,将读入的数据块放置到LRU中最近最常使用的一端。这样,数据库缓存中利用LRU算法对缓存块进行换入、换出调度时,就不会将属于这个表的数据块立即换出,从而提高了针对表的查询效率
默认是NOCACHE
对于比较小且又经常查询的表,用户在创建表时指定CACHE子句,以便利用系统缓存来提高对该表的查询效率
如:在DD--user_tables 中查询students_6表是否启用了缓存功能
select table_name,cache from user_tables where table_name=‘STUDENTS_6‘;
维护数据表
普通用户只能对自己模式中的表进行修改,如果要对任何模式中的表进行修改操作,用户必须具有ALTER ANY TABLE系统权限
增加和删除字段
如:在students_6 表中增加一个province新字段
alter table students_6 add(province varchar2(10));
在students_6中删除province字段
alter table students_6 drop column province;
如果要删除多列,则不能使用column ,(,)用这种方式表示
说明:在删除字段时,系统将删除表中每条记录对应的字段值,同时释放所用占用的存储空间,并且不会影响到表中其他列的数据。如果要删除一个大型表中的字段,由于需要对每条记录进行处理,删除操作可能会执行很长时间。
修改字段
更改时,要注意,在有数据的情况下,只能将数据的长度从低想高改,而没有数据则随意(甚至是改变数据类型)
如:将students_6表中的departno字段的长度由2更改为4:
alter table students_6 modify departno varchar2(4);
注意这种修改只对今后插入的数据起作用。
重命名字段
alter table students_6 rename column departno to deptno;
重命名表
对表重命名很容易,但是影响却非常大,在对表的名称进行修改时,要格外小心。虽然Oracle可以自动更新数据字典中的外键、约束定义以及表关系,但是它不能更新数据库的存储过程、客户应用,以及依赖该对象的其他对象
如:将students_6重命名为students_7
alter table students_6 rename to students_7;
改变表空间和存储参数
1.修改表空间
如:将students_6表由表空间play移动到tbsp_2表空间
alter table students_6 move tablespace tbsp_2;
移动表空间会将数据从物理结构上的一个数据文件移动到另一个数据文件
2.修改存储参数
主要是指修改pctfree pctused 若改变了这两个参数,则表中所有的数据块都将收到影响,而不论数据块是否已经使用
如:使用alter table重新设置students_6表的pctfree pctused
alter table students_6 pctfree 25 pctused 45;
删除表
数据表在创建之后 ,根据实际情况需求,用户可以将其删除。但需要注意的是,一般情况下用户只能删除自己模式中的表,如果要删除其他模式的表,则必须具有DROP ANY TABLE 系统权限
删除一个表的结构时,通常Oracle会执行以下操作:
删除表中所有的数据
删除与该表相关的所有索引和触发器
如果有视图或PL/SQL过程依赖于该表,这些视图或PL/SQL过程将置于不可用状态
从DD中删除该表的定义
回收为该表分配的存储空间
--有一个可选项cascade constraints ,使用该参数时,drop table不仅删除该表,而且所有引用这个表的视图、约束或触发器也都被删除了
如:删除表students_5以及所有引用这个表的视图、约束或触发器
drop table students_5 cascade constraints;
一般情况下,并没有彻底删除(仅仅在DD中被除名),而是把该表放到了回收站,可以使用flashback闪回进行还原
可以通过DD--recyclebin(original_name--表名,object_name)查询该表是否在回收站中
如:用falshback恢复删除的students_5
flashback table students_5 to before drop;
当然,如果想在删除时,立即释放空间,则可以使用purge,这样表就彻底删除了
修改表的状态
在Oracle11g之前,不能将表单独设为read only,只能对表空间或数据库置为read only
如:将表students_5 至于只读
alter table students_5 read only(read write);
处于只读状态的表,不能进行DML,但是可以移动表空间
数据完整性和约束性
在对约束的定义,可以在create table 中,也可以在alter table中 ,一般是先定义表的字段;然后再根据实际需要通过alter table为表添加约束
A--非空约束
就是限制必须为某个列提供值。空值(NULL)是不存在值,默认情况下,列是允许NULL的
如:创建books表,要求bookno (图书编号),ISBN和publishno(出版社编号)不能为空值
create table books(
bookno number(4) not null,
bookname varchar2(20),
author varchar2(10),
saleprice number(9,2),
publisherno varchar2(4) not null,
publishdate date,
ISBN varchar2(20) not null)
/
此时,可以使用
alter table books modify bookname not null;
如果,在修改not null时,该列数据已经存在,那么将修改失败。
B--主键约束
用于唯一标识表中的每一行记录。在一个表中,最多只有一个主键约束,主键约束既可以由一个列组成,也可以由两个或两个以上的列(联合主键)组成
主键约束同时具有非空约束。
如果主键约束由一列组成,该主键约束被成为行级约束。如果主键约束由两个或两个以上的列组成时,则该主键称为表级约束
可以在创建表中使用关键字constraints ... primary key
如:创建表books_1 ,并为该表定义行级主键约束BOOK_PK(主键列为bookno):
create table books_1(
bookno number(4) not null,
bookname varchar2(20),
author varchar2(10),
saleprice number(9,2),
publisherno varchar2(4) not null,
publishdate date,
ISBN varchar2(20) not null,
constraints BOOK_PK primary key(bookno))
/
如果用户在创建表时,没有指定主键可以使用alter table add constraint ... primary key
如:使用alter table .. add语句为books添加主键约束
alter table books
add constraints Books_PK primary key(bookno);
这里,如果指定约束名称,则必须加constraints,而如果使用系统自动分配的名称,则不需要该关键字
比如:在创建表中,bookno number(4) primary key
同样在alter table add primary key(bookno)
都可以添加系统自动命名的约束名
注意:如果表中已经存在一个主键约束,那么当视图为该表再增加一个主键约束时,系统会产生一个错误信息(即使在不同的列增加也是如此)。同样,如果给表中添加主键时,该表中已经存在数据,并且主键列具有相同的值或NULL,那么添加主键约束将失败。
删除主键约束:
alter table books_1 drop constraints BOOK_PK;
同时,增加主键的列要根据实际情况
C--唯一性约束
唯一性,强调所在的列不允许有相同的值。就是为了解决可以为空而又不能重复的值的列的类型
如:创建一个会员表members,并要求为该表的QQ列定义唯一性约束:
create table members(
memno number(4) not null,
memname varchar2(20) not null,
phone varchar2(20),
email varchar2(30),
QQ varchar2(20) constraints QQ_UK unique,
provcode varchar2(2) not null,
occucode varchar2(2) not null,
indate date default sysdate,
constraint Mem_PK primary key (memno))
/
到此,我发现了一个神奇的现象,constraint 和constraints 一样使用,百度说,PL/SQL自动生成的sql文件是不带s的
添加unique的列有值,则不允许重复,但是可以插入多个NULL值,也就是说,该列的空值是可以重复的,所以为了防止这种情况,可以在该列上添加not null 约束。那这样该列的约束就基本上相当于primary key 了
D--外键约束
一般外键约束会使用两个表进行关联(也存在同一个表自连接的情况)。当前表(外键表)的引用列必须和被引用表(主键约束或唯一约束)的值一致,如果删除被引用表的该列数据时,该数据也不能出现在引用表中,如果引用表中存储了被引用表中将要被删除的数据,那么对被引用表的删除操作将失败
如:建立emoloyees_temp和departments表关联的外键约束
alter table employees_temp
add constraint temp_departid_fk
foreign key(department_id)
references departments(department_id)
/
当然了,如果外键表中的外键列与被引用表的被引用列列名相同,那么可以省略,references后面的列名
在定义外键约束时,可以使用关键字on来确定引用行为:
no action:当删除被引用表中被引用列的数据时,将违反外键约束,该操作将被禁止执行,default
set null:当被引用表的引用列的数据被删除时,外键表中外键列被设置为null,要是这个关键字起作用,那么该外键列必须支持NULL 值
cascade:当被引用表中被引用列的数据被删除时,外键表中对应的数据也将被删除,这种删除方式通常称为“级联删除”
如:在HR模式中,创建一个新表departments_temp,然后该表与employees_temp建立外键约束,并指定外键约束引用类型为on delete cascade
alter table employees_temp
add constraint temp_departid_fk2
foreign key(department_id)
references departments_temp on delete cascade;
禁用和激活约束
约束的存在会降低插入和更改数据的效率,系统必须确认这些数据是否满足定义的约束条件。因此,在某些场合下,如从SQL * Loader从外部数据源向表中导入大量数据,并且事先知道这些数据是满足约束条件的,为提高执行效率,就可以禁用这些约束。
之一:定义时约束禁用--disable
如:创建学生信息表student,并为年龄列(AGE)定义一个disable状态的check约束(要求年龄值0-120):
create table student(
stucode varchar2(4) not null,
stuname varchar2(10) not null,
age int constraint AGE_CK check (age>0 and age<120) disable,
province varchar2(20),
schoolname varchar2(50))
/
之二:禁用已经存在的约束--alter table disable constraint
如:禁用employees_temp 表中的约束temp_departid_fk
alter table employees_temp disable constraint temp_departid_fk;
注意:在禁用主键约束时,Oracle会默认删除约束对应的唯一索引;而在重新激活约束时,Oracle将会重新建立唯一索引,如果希望在删除约束时保留对应的唯一索引,可以在禁用约束时使用关键字keep index(通常放在约束名后面)
如果在禁用唯一约束或主键约束时,如果有外键正在引用该列,则无法禁用唯一或主键约束的。这时,可以先禁用外键约束,然后再禁用唯一或主键约束;或者在禁用唯一、主键约束时使用cascade,这样可以级联禁用这些列的外键约束
禁用也只是暂时的,可以使用alter table enable constraint...
--novalidate|validate: novalidate表示该在激活约束时不验证表中已经存在数据是否满足约束,默认是validate,也就是会检查
当出现由于重复数据无法解禁时,要先更改这些重复字段,再解禁即可