本节实验主要讲解了 Oracle 的表操作,如何实现对表进行创建、重重命名、复制、删除和修改等。
- 常用数据类型
- 表的创建
- 表的重命名
- 截断表
- 表的复制
- 表的删除
- 修改表的结构
以下是介绍一些我们最常用的数据类型:
- 字符串:使用
VARCHAR2
描述(其他数据库用 VARCHAR)。例如姓名,地址等。 - 数字:使用
NUMBER
描述。如果要描述小数则使用NUMBER(p,s)
,其中s
是小数位(scale),p-s
是整数位,例如number(4,2)
代表存储小数位数为 2,总长度最多为 4 的浮点数。也可以用INT
描述整数,FLOAT
描述小数。 - 日期:使用
DATE
描述。Oracle 里的 DATE 包含有日期时间。其他数据库一般 DATE 只是日期,DATETIME 才表示日期时间。 - 大文本数据:使用
GLOB
描述。最多可以保存4G
的文字信息。
想了解更多数据类型可参考Oracle SQL 数据类型
语法:
CREATE TABLE 表名称(
列名称 类型 [DEFAULT 默认值]
列名称 类型 [DEFAULT 默认值]
...
)
例如:
注:前面的 SQL>
不用输入,只是为了说明是在 SQL 命令行输入内容。
SQL> CREATE TABLE student(
id NUMBER,
name VARCHAR2(20),
age number(3),
birthday DATE DEFAULT SYSDATE,
note CLOB
);
查看是否已经创建好 student 表:
SQL> select * from tab where tname='STUDENT';
查看 student 表结构:
SQL> desc student;
我们可以向其中插入数据:
SQL> INSERT INTO student(id,name,age,birthday,note) VALUES (1,'syl',19,TO_DATE('1999-01-01','yyyy-mm-dd'),'note test');
SQL> INSERT INTO student(id,name,age,birthday,note) VALUES (2,'lou',21,TO_DATE('1997-01-01','yyyy-mm-dd'),'note test');
查看我们插入的数据:
SQL> select * from student;
例如我们查询出 student 表中 name 字段值为 syl 的记录,通过查询结果创建一个 名叫 syl_stu 的表。
SQL> create table syl_stu as select * from student where name='syl';
SQL> select * from syl_stu;
SQL> RENAME student TO stu;
我们使用数据字典查询一个用户全部的数据表,可以发现表已经被更名:
SQL> select * from user_tables;
列出数据库表对象的全部信息内容,例如名称,存储情况等。
数据字典:记录所有对象的信息。
- 用户级别:user_*,指一个用户可以使用的数据字典。
- 管理员级别:dba_*,指由数据库管理员使用的数据字典。
- 全部级别:all_* ,指不管是用户还是管理员都可以使用。
首先我们使用 desc
来查看表的结构。
SQL> desc stu;
名称 空值 类型
-------- -- ------------
ID NUMBER
NAME VARCHAR2(20)
AGE NUMBER(3)
BIRTHDAY DATE
NOTE CLOB
接下来我们来修改表的结构。
例一:为 stu
表增加一列 address
,设默认值为 none。
SQL> alter table stu add(address varchar2(50) default 'none');
然后查看表中数据会发现多了 address 列,并且值为 none:
SQL> select * from stu;
例二:为 stu
表增加一列 email
,不设默认值。
SQL> alter table stu add(email varchar2(50));
再次查看表,会发现多了 email 列,并且为 null。
SQL> select * from stu;
例一:修改 stu
表的 name
列的类型为 varchar2(30)
。
SQL> alter table stu modify (name varchar2(30));
例二:修改 stu
表的 email
列的默认值为 no email
。
SQL> alter table stu modify (email default 'no email');
注意:虽然这里我们设置了默认值,但是以前插入的数据的 email
列的值仍然是 null,只有我们新插入的数据的 email
列的值才默认为 no email
,如下所示:
SQL> select * from stu;
SQL> INSERT INTO stu(id,name,age,birthday,note) VALUES (3,'plus',19,TO_DATE('1999-01-01','yyyy-mm-dd'),'note test');
SQL> select * from stu;
例:将 address
列的名称改为 saddress
。
SQL> alter table stu rename column address to saddress;
重命名列还有一个作用就是在要删除一个列的时候,用来确认是否有用户或应用程序正在使用此列,如果有的话,就会报错。
例:将 saddress
列删除。
SQL> alter table stu drop (saddress);
或者使用
SQL> alter table stu drop column saddress;
在删除一列的时候如果数据太多,通常需要一定时间,如果想快速使用户或应用程序不能访问某些列的时候,可以使用 unused
标记列。例如下面我们标记 email
列:
SQL> alter table stu set unused (email);
标记过后使用 desc stu
查看会发现没有显示 email
列,但是它并没有真正被删除,执行下面的语句可以删除所有被 unused
标记的列。
SQL> alter table stu drop unused columns;
复制表结构类似于用查询创建表,只是修改了 where
条件。例如,我们要复制 stu
的表结构。
SQL> create table stu_cp as select * from stu where 1=2;
该语句只是复制了结构,并没有复制其数据:
SQL> desc stu_cp;
SQL> select * from stu_cp;
有时候我们存储的数据需要满足某些条件,例如:假设我们定义一个学生表,表中每个学生的学号和身份证号码是不可以重复的,学生的学号不能为空等等。这就是约束,数据库上为了保证数据表中的数据完整性而增加了约束。
约束一共有六种:数据类型,非空约束,唯一约束,主键约束,检查约束,外键约束。
注意:约束太多,会导致更新速度缓慢,有些验证操作应交给应用程序去做。
非空约束(NK)指表中的某一个字段的内容不允许为空。使用 not null
声明。
例:创建一个名叫 tech
的表,表中有 id
和 name
两个字段。设置 name
字段不为空。
SQL> create table tech(id number,name varchar2(20) not null);
下面我们就来插入一条没有 name 的数据。
SQL> insert into tech(id) values (2);
你会发现报错了 ORA-01400: 无法将 NULL 插入 ("SYSTEM"."TECH"."NAME")
。
唯一约束(UK)指表中某一字段内容不允许重复。使用 unique
。
例:为表 tech
增加一列 email
,不允许重复。
SQL> alter table tech add(email varchar2(30) unique);
下面来插入两条 email 重复的数据:
SQL> insert into tech(id,name,email) values (2,'syl2','[email protected]');
SQL> insert into tech(id,name,email) values (3,'syl3','[email protected]');
报错 SQL 错误: ORA-00001: 违反唯一约束条件 (SYSTEM.SYS_C007385)
。这个 SYS_c007385
实际上就是约束的对象信息(约束也是数据库对象),可以从数据字典中查到。
注意:这个对象信息可能跟你的报错不一样,实际查询时,要改为你自己实际看到的对象信息才可以查询到。
-- 格式化
SQL> col owner for a10;
SQL> col constraint_name for a20;
SQL> col table_name for a15;
SQL> col column_name for a20;
-- 查询
SQL> select owner,constraint_name,table_name,column_name from user_cons_columns where constraint_name='SYS_C007385';
输出结果如下:
OWNER CONSTRAINT_NAME TABLE_NAME COLUMN_NAME
---------- -------------------- --------------- --------------------
SYSTEM SYS_C007385 TECH EMAIL
可以看到这个约束是在 TECH
表的 EMAIL
列。
这样去数据字典中查还是比较麻烦,我们可以使用下面的方式创建唯一约束,这样能够直接根据报错知道是哪一个字段违反了约束条件。例如我们增加 cid
字段,添加唯一约束。
SQL> alter table tech add(cid number,constraint uk_cid unique(cid));
注意:设置的约束名称(这里是
uk_cid
)不可以重复。
向里面插入数据:
SQL> insert into tech(id,name,email,cid) values (3,'syl3','[email protected]',1);
SQL> insert into tech(id,name,email,cid) values (4,'syl4','[email protected]',1);
报错 SQL 错误: ORA-00001: 违反唯一约束条件 (SYSTEM.UK_CID)
。
主键约束(PK)= 非空约束 + 唯一约束 。主键约束在每一个数据表中只有一个,但是一个主键约束可以由数据表中多个列组成。一般我们只把一个字段定义成主键。
例:为表 tech
添加主键约束
SQL> alter table tech add constraints pk_id primary key(id);
检查约束(CK)限定数据的正确性。
例一:设定性别只能为 man
或者 female
。
SQL> alter table tech add (sex varchar2(10),constraints chk_sex check(sex='man' or sex='female'));
例二:设定年龄在 5 到 200 岁。
SQL> alter table tech add (age number(3),constraints chk_age check(age between 5 and 200));
或者
SQL> alter table tech add (age number(3),constraints chk_age check(age>=5 and age<=200));
比如我们现在有两张表,实验楼的课程表和课程类别表。一个课程是属于一个类别的。我们在课程表中增加了一个字段来描述课程的类别。这个字段的值来自于课程类别表的类别 id 。为了不允许插入类别表中类别 id 以外的值,我们就定义一个外键约束。
-- 类别表
SQL> create table syl_category(
cid number(5) primary key,
name varchar2(30)
);
-- 课程表
SQL> create table syl_course(
id number(10) primary key,
name varchar2(30),
cid number(5),
constraint fk_cate foreign key(cid) references syl_category(cid) on delete cascade
);
上面的
syl_category
表就叫父表 ,syl_course
表就叫子表 。
on delete cascade
表示当 syl_category 表中的 cid 被删除时,对应的 syl_cource 表中的 cid 也会被删除。
向其中插入数据:
SQL> insert into syl_category(cid,name) values (1,'cate1');
SQL> insert into syl_course(id,name,cid) values (1,'course1',1);
SQL> insert into syl_course(id,name,cid) values (2,'course1',2);
会发现第三句报错 SQL 错误: ORA-02291: 违反完整约束条件 (SYSTEM.FK_CATE) - 未找到父项关键字
语法:
SQL> alter table <table_name> drop constraint <constraint_name>;
例如我们删除表 tech
的 sex
字段的检查约束 chk_sex
。
SQL> alter table tech drop constraint chk_sex;
首先我们来进行普通的删除操作。
SQL> commit;
SQL> delete from stu;
查看表内容会发现已经被清空。但是在我们执行 rollback
回滚操作过后会发现数据又被恢复:
SQL> rollback;
SQL> select * from stu;
rollback 会恢复到上一次 commit 的数据。
上面的删除操作并没有立即将表所占的资源(约束,索引等)立即释放掉,如果想要完全删除,就需要使用 truncate
,也叫做截断表的操作。例如:
SQL> truncate table stu;
这个时候再执行回滚操作,会发现数据无法恢复:
SQL> rollback;
SQL> select * from stu;
例如我们要删除 syl_stu
这张表,可以使用如下命令:
SQL> drop table syl_stu;
注意:如果删除的表是含有约束的父表的话,将会报错。此时需要使用
drop table <table_name> cascade constraints
删除。