实验二
SQL语言
实验目的
熟悉并掌握创建表,插入记录,查询记录,删除记录,修改记录。
创建索引,删除索引。
创建视图,使用视图,删除视图。
实验内容
现有一个单位内部的小型图书借阅系统,假设每本图书的数量无限制,并且可以借给任何单位成员,每个单位成员可以借多本书,单位成员与图书的关系是多对多的关系。假设系统中仅有三个关系模式。
数据表结构
Reader表
属性名 |
类型 |
长度 |
是否空 |
含义 |
RNO |
varchar2 |
4 |
|
员工编号(主码) |
Rname |
varchar2 |
10 |
否 |
员工姓名 |
Rsex |
varchar2 |
2 |
|
性别 |
Rage |
integer |
integer |
|
年龄 |
Rboss |
varchar2 |
10 |
|
直接上司 |
Raddress |
varchar2 |
30 |
|
办公地点 |
Book表
属性名 |
类型 |
长度 |
是否空 |
含义 |
BNO |
varchar2 |
4 |
|
书本编号(主码) |
Bname |
varchar2 |
50 |
否 |
书名 |
Bauthor |
varchar2 |
50 |
|
作者 |
Bpress |
varchar2 |
50 |
|
出版社 |
Bprice |
varchar2 |
numeric(6,2) |
|
价格 |
RB表
属性名 |
类型 |
长度 |
是否空 |
含义 |
RNO |
varchar2 |
4 |
|
员工编号 |
BNO |
varchar2 |
4 |
|
书本编号 |
RBdate |
date |
|
|
借阅日期 |
|
|
|
|
|
部分提示(黄色底的代码可以直接粘贴运行):
create user cc identified by ccpassword ;
grant resource, connect, DBA to cc;
Declare
tmp integer default 0;
Begin
select count(*) into tmp from user_tables where table_name='RB';
if(tmp>0) then
execute immediate 'drop table RB';
end if;
select count(*) into tmp from user_tables where table_name='READER';
if(tmp>0) then
execute immediate 'drop table READER';
end if;
select count(*) into tmp from user_tables where table_name='BOOK';
if(tmp>0) then
execute immediate 'drop table BOOK';
end if;
end;
问:为何要先删去RB?能不能先删去READER?
create table Reader
(
RNO varchar2(4) primary key,
Rname varchar2(10) not null,
Rsex varchar2(2),
Rage integer,
Rboss varchar2(10),
Raddress varchar2(30)
) ;
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R001','张三',20,'男','李四','416');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R002','张三',35,'女',null,'417');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R003','李四',30,'男',null,'416');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R004','王五',20,'男',null,'417');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R005','马六',40,'男',null,'416');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R006','刘三',20,'男',null,'417');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R007','王四',40,'男','李四','416');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R008','李小龙',20,'男','李四','417');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R009','王小倩',40,'男','李四','416');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R010','王一小',20,'男','李四','417');
select Rname from Reader where Rboss='李四';
UPDATE reader SET Raddress='420' WHERE rboss='李四';
DELETE FROM reader WHERE rboss=NULL;
DROP TABLE reader;
create table reader2 as select * from reader; --创建表格reader2
查看这两个数据表的结构、内容是否相同?分别执行:
desc reader;
desc reader2;
也可以在可视化界面查看这两个表所附带的约束
update reader set RNO='R001' where Rname='张三';
表reader中的RNO是primary key,更新后的RNO与现存的RNO重复,违反唯一约束条件
update reader2 set RNO='R001' where Rname='张三';
insert into reader2(RNO,Rname,Rsex,Rage,Rboss, Raddress) values(null,'lisi',null,null,null,null);
READER2
DROP TABLE READER2;
create table Book
(
BNO varchar2(4),
Bname varchar2(50) not null,
Bauthor varchar2(50),
Bpress varchar2(50),
Bprice numeric(6,2),
primary key(BNO)
);
insert into book (BNO,Bauthor,Bname, bpress, bprice) values('B001','严蔚敏','数据结构','清华大学出版社',null);
insert into book (BNO,Bauthor,Bname, bpress, bprice) values('B002','唐发根','数据结构','北航出版社',24);
insert into book (BNO,Bauthor,Bname, bpress, bprice) values('B003','王珊','数据库原理','高等教育出版社',40);
insert into book (BNO,Bauthor,Bname, bpress, bprice) values('B004','张飞','数据库原理','清华大学出版社',30);
insert into book (BNO,Bauthor,Bname, bpress, bprice) values('B005','王珊','数据库原理','清华大学出版社',null);
create table RB
(
RNO varchar2(4),
BNO varchar2(4),
RBdate date default sysdate,
primary key(RNO,BNO),
foreign key (RNO) references Reader(RNO),
foreign key (BNO) references Book(BNO)
);
insert into RB (RNO,BNO) values ('R001','B001');
insert into RB (RNO,BNO) values ('R001','B002');
insert into RB (RNO,BNO) values ('R001','B004');
insert into RB (RNO,BNO) values ('R002','B001');
insert into RB (RNO,BNO) values ('R003','B001');
insert into RB (RNO,BNO) values ('R004','B001');
insert into RB (RNO,BNO) values ('R004','B002');
insert into RB (RNO,BNO) values ('R005','B001');
insert into RB (RNO,BNO) values ('R006','B001');
insert into RB (RNO,BNO) values ('R006','B003');
insert into RB (RNO,BNO) values ('R006','B005');
insert into RB (RNO,BNO) values ('R006','B002');
insert into RB (RNO,BNO) values ('R006','B004');
初始数据
reader表
RNO |
RNAME |
RSEX |
RAGE |
RBOSS |
RADDRESS |
R001 |
张三 |
男 |
20 |
李四 |
416 |
R002 |
张三 |
女 |
35 |
|
417 |
R003 |
李四 |
男 |
30 |
|
416 |
R004 |
王五 |
男 |
20 |
|
417 |
R005 |
马六 |
男 |
40 |
|
416 |
R006 |
刘三 |
男 |
20 |
|
417 |
R007 |
王四 |
男 |
40 |
李四 |
416 |
R008 |
李小龙 |
男 |
20 |
李四 |
417 |
R009 |
王小倩 |
男 |
40 |
李四 |
416 |
R010 |
王一小 |
男 |
20 |
李四 |
417 |
book表中数据
BNO |
BNAME |
BAUTHOR |
BPRESS |
BPRICE |
B002 |
数据结构 |
唐发根 |
北航出版社 |
24 |
B003 |
数据库原理 |
王珊 |
高等教育出版社 |
40 |
B004 |
数据库原理 |
张飞 |
清华大学出版社 |
30 |
B005 |
数据库原理 |
王珊 |
清华大学出版社 |
|
B001 |
数据结构 |
严蔚敏 |
清华大学出版社 |
|
RB表中数据
RNO |
BNO |
RBDATE(实验时间) |
R001 |
B001 |
插入数据时的系统时间 |
R001 |
B002 |
|
R001 |
B004 |
|
R002 |
B001 |
|
R003 |
B001 |
|
R004 |
B001 |
|
R004 |
B002 |
|
R005 |
B001 |
|
R006 |
B001 |
|
R006 |
B003 |
|
R006 |
B005 |
|
R006 |
B002 |
|
R006 |
B004 |
|
以下为查询READER表中创建的约束类型,其中constraint_type为约束类型,该属性值的取值Type Code如下表所示。(可以根据上课所讲的实体完整性、参照完整性、用户自定义完整性理解以下约束类型;直接在SQL DEVELOPER中双击表格也可以查看在表上所建立的约束)
select table_name,constraint_name,constraint_type from user_constraints where table_name ='READER';
Type Code |
Type Description |
Acts On Level |
C |
Check on a table |
Column |
O |
Read Only on a view |
Object |
P |
Primary Key |
Object |
R |
Referential AKA Foreign Key |
Column |
U |
Unique Key |
Column |
V |
Check Option on a view |
Object |
方法一:先把RB中所有’R010’的借书记录都删掉
方法二:修改数据表READER的结构,允许级联删除(注:ORACLE不支持级联更新)。
alter table rb add constraint MYFK foreign key(rno) references reader(rno) on delete cascade;
系统提示:SQL 错误: ORA-02275: 此表中已经存在这样的引用约束条件
可见,首先要先删去原来的约束,因建表时没给该约束命名,故应查这个约束的名字,才能删去。注意,这个名字由系统自动赋值,不同的环境下约束名可能不同):
alter table rb drop constraint SYS_C0011303;
alter table rb add constraint MYFK foreign key(rno) references reader(rno) on delete cascade;
再执行:delete from reader where rno='R010';
顺利删去一行,打开RB表,发现前面插入的('R010','B005')也不在了。
alter table reader ADD Rbirthday integer ;
alter table reader DROP column Rbirthday;
alter table reader modify Raddress varchar2(50);
alter table book add constraint bp check (Bprice BETWEEN 10 and 100);
alter table Reader add constraint rr check (Rage BETWEEN 16 and 60);
drop table reader CASCADE;
drop table reader CASCADE CONSTRAINTS;
drop table rb CASCADE CONSTRAINTS;
drop table book CASCADE CONSTRAINTS;
索引的建立与删除
create unique index myindex on reader(rname);
报告出错:"cannot CREATE UNIQUE INDEX; duplicate keys found"
如何修改表格数据,再建索引
解决方法很简单,要么把数据库的数据清理掉;要么把你要创建唯一索引的那一列重复的数据删掉。我选择的是创建唯一索引的那一列重复的数据删掉一个。
drop index myindex;
视图
grant resource, connect, DBA to cc;
否则系统显示没有创建视图的权限。执行完之后再回到CC的连接:
CREATE VIEW V416 as select rno,rname,rage from reader where raddress='416'
确认该视图的存在:
select * from v416
SELECT rno,rname from v416 WHERE rage>30;
insert into v416( rno,rname,rage) values('R999','new reader',99);
select * from reader
select * from v416
插入成功了吗?为什么通过视图插入的纪录在视图中看不见?
刚插入数据条件不满足此视图的条件了
CREATE VIEW V417 as select rno,rname,rsex,rage,raddress from reader where raddress='417' with check option;
select * from v417
insert into v417( rno,rname,rage) values('R777','417 reader',66);
执行不成功。
drop view v417;
CREATE VIEW V417 as select rno,rname,rsex,rage,raddress from reader where raddress='417' with check option;
insert into v417( rno,rname,rage,raddress) values('R777','417 reader',66,'417');
执行成功。
select * from v416;
delete from v416 where rname='王小倩';
select * from v416;
CREATE VIEW FV417 as select * from V417 where RSEX='女';
select * from FV417;
SELECT * FROM V417;
Delete from v417 where v417.rno not in (SELECT rno from rb);
SELECT * FROM V417;
SELECT BNO,COUNT(*) FROM RB GROUP BY BNO;
CREATE VIEW GV(BNO,COUNTS) AS SELECT BNO,COUNT(*) FROM RB GROUP BY BNO;
SELECT * FROM GV;
思考是否可以向GV中插入数据,为什么?
不可以向GV插入数据,因为GV的内容并非数据,而是数据和相关数据统计结果。
drop view v417
触发器(可不做,时间多再做)
参考PLSQL帮助文档,试试建立一个触发器。在用户执行删除某个员工的时候触发,该触发器的功能是先删除RB中该员工的借书记录,然后删除Reader中该员工记录。
实验报告要求
写出实验步骤及相关的SQL语句即可。