实验三
SQL查询数据
实验目的
熟练掌握使用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;
- 以用户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?
因为RB表中定义了外键RNO(关联Reader)和BNO(关联Book),如果先删去READER就会违反了参照完整性。
foreign key (RNO) references Reader(RNO),
foreign key (BNO) references Book(BNO)
- 拷贝代码运行,建立表格及输入数据:
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');
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 |
|
单表查询
- 查询全体员工的姓名和出生年份;
SELECT RNAME,'Year of Birth: ' ,2019-RAGE FROM reader;
- 查询工作在416房间的员工的所有信息;
SELECT RNO,RNAME,RSEX,RAGE,RBOSS FROM reader where RADDRESS='416';
- 查询年龄在30到50岁之间的员工姓名、年龄;
select rname,rage from reader where rage BETWEEN 30 and 50;
- 查询借了书的员工的编号,排除相同的元素;
select DISTINCT rno from rb
- 查询名字中包含字“小”的员工姓名、办公地点;
select rname ,raddress from reader where rname like '%小%';
- 查询名字中第二个字为“小”的员工姓名、办公地点;
select rname,raddress from reader where rname like '_小%' ;
注:ORACLE只需一个下划线符号代表一个汉字
- 查询所有不姓“李”的员工姓名、性别;
select rname,rsex from reader where rname not like '李%';
- 查询Book表中价格不为空值的书名、出版社;
select bname,bpress,bprice from book;
select bname,bpress,bprice from book where bprice is not null;
- 查询清华大学出版社和高等教育出版社出版的所有书籍,按照出版社降序、书名升序排列;
select * from book;
上面的语句用来查看后面的语句结果对不对。
select * from book where bpress='清华大学出版社'or bpress='高等教育出版社' ORDER by bpress desc,BNAME asc;
- 查询员工的总人数
SELECT COUNT(*) FROM READER
- 查询借了书的员工的人数
SELECT COUNT(*) FROM READER WHERE READER.RNO IN (SELECT RNO FROM rb);
或:
SELECT COUNT(DISTINCT rno) FROM RB
- 查询“张三”所借图书的数量;
select COUNT(*) from rb where rno in (SELECT RNO FROM reader where rname='张三')
- 查询最贵的书籍的作者姓名;
select bname,bauthor,bprice from book where bprice=(SELECT MAX(bprice)FROM BOOK);
- 查询Book表中书籍的平均价格,查询结果说明了什么;
select AVG(bprice) from book
去掉了空值
- 查询book中包含的各个出版社及其出版书籍的数量;
SELECT bpress,'nount of bpress: ' ,COUNT(bpress)FROM book GROUP BY bpress, 'nount of bpress: ';
复合查询
- 查询每个员工及其借书情况,列出员工编号、姓名和借书日期
select reader.rno,rname,rbdate from reader,rb where reader.rno in rb.rno;
- 查询每个员工及其借书所有字段(没有借书的员工也列出来);(用左外连接)
select reader.rno,rname,rsex,rb.bno,rbdate from reader left outer JOIN rb on reader.rno=rb.rno ;
- 查询与“李小龙”工作在同一个办公室的员工信息(用两种方法:自身连接、子查询);
自身连接:select b.rname from reader a, reader b where b.raddress = a.raddress and a.rname = '李小龙' and b.rname != '李小龙';
子查询:select RNAME from READER WHERE RADDRESS= (select RADDRESS from READER where rname='李小龙');
- 查询借阅了“数据库原理”的员工所有信息(两种方法:连接查询、子查询)
Select rbdate,rage,rboss,reader.rno,rname,rsex,raddress from reader,rb,book where book.bname='数据库原理'and book.bno=rb.bno and rb.rno=reader.rno;
select RNO,RNAME,RSEX,RADDRESS from READER where RNO in (SELECT rno from rb where bno in(select bno from book where bname='数据库原理'));
问:为什么最后的子句不能是bno=( )?
因为表READER里没有bno这个属性列。
- 查询小于或等于同一办公室中成员的平均年龄的员工编号、姓名、年龄。
select RNO,RNAME,RAGE,RADDRESS from READER order by raddress;
select raddress,avg(rage) from reader group by raddress ;
上面的两句用来查看后面的语句结果对不对。
select a.rno,a.rname,a.rage,a.raddress from reader a where a.rage<=(SELECT avg(rage)from reader b where a.raddress=b.raddress);
- 查询比所有数据库原理价格都低、并且不是清华大学出版社出版的书籍的信息;
select * from BOOK where BNAME='数据库原理';
select min(BPRICE) from BOOK where BNAME='数据库原理';
select * from BOOK;
上面的语句用来查看后面的语句结果对不对。
select * from book where bprice<any(SELECT bprice from book where bname='数据库原理')and bpress!='清华大学出版社';
- 查询借阅了B001的员工的编号、姓名、办公室;
select READER.RNO,RNAME,RADDRESS from READER;
select * from rb where bno='B001';
上面的语句用来查看后面的语句结果对不对。
select reader.rno,rname,raddress from reader,rb where reader.rno=rb.rno and rb.bno='B001';
- 查询没有借阅B001的员工的编号、姓名、办公室;
select rno,rname,raddress from reader where rno NOT IN (select reader.rno from reader,rb where reader.rno=rb.rno and rb.bno='B001');
- 查询借阅了所有书籍的员工的姓名;
select bno from book;
select reader.rno,rname,rb.bno from rb left outer join reader on (reader.rno=rb.rno);
上面的语句用来查看后面的语句结果对不对。
select RNAME from READER
where not exists (select * from book where not exists(select *from rb where bno=book.bno and rno=reader.rno));; //参考课本P111【例46】
注:前两句SELECT是为了显示原数据表的数据,以检查查询结果是否正确。
- 查询至少借阅了编号为R004的员工借阅的全部书籍的员工姓名、性别、办公室
Select * From Rb Where Rno='R004';
select reader.rno,rname,rb.bno from rb left outer join reader on (reader.rno=rb.rno);
上面的语句用来查看后面的语句结果对不对。
Select Rname,Rsex,raddress From Reader
Where not exists (select * from rb a where a.rno='R004'AND not exists (select * from rb b where b.rno=reader.rno and a.bno=b.bno)); //参考上一题
注:前两句SELECT是为了显示原数据表的数据,以检查查询结果是否正确。
- 查询年龄大于30岁或者工作在416的员工信息(用集合查询完成)
Select * from reader where rage>30 union Select * from reader where raddress='416';
- 查询年龄大于30岁并且工作不在416的员工信息(用集合查询完成)
Select * from reader where rage>30 minus Select * from reader where raddress='416' ;
注意:ORACLE的集合减,不是’except’,而是’ minus’
实验报告要求
写出实验步骤及相关的SQL语句即可。