-- 九、 子查询
-- 无关子查询
-- 比较子查询:能确切知道子查询返回的是单值时,可以用>,<,=,>=,<=,!=或<>等比较运算符。
-- 49、 查询与“俞心怡”在同一个部门的读者的借书证编号、姓名、部门。
select 借书证编号, 姓名, 部门 from 读者 where 部门 = (select 部门 from 读者 where 姓名 = '俞心怡');
select 借书证编号, 姓名, 部门 from 读者 where 部门 = (select 部门 from 读者 where 姓名 = '俞心怡');
-- 50、 查询“喻明远”的借阅信息,包括:借书证编号、图书条码号、借出日期。
select 读者.借书证编号, 图书条码号, 借出日期 from 读者, 借阅 where 读者.借书证编号 = 借阅.借书证编号 and 姓名 = '喻明远' ;
select 读者.借书证编号, 图书条码号, 借出日期 from 读者, 借阅 where 读者.借书证编号 = 借阅.借书证编号 and 姓名 = '喻明远' ;
-- 51、 查询和图书条码为‘0000018’的图书相同出版社的图书
select 书名, 出版社
from 图书详情
where ISBN in (select ISBN from 图书 where 图书条码号 = '0000018');
select 书名, 出版社
from 图书详情
where ISBN in (select ISBN from 图书 where 图书条码号 = '0000018');
-- SOME、ANY、ALL和IN子查询:
-- WHERE 比较运算符[ NOT ] ALL ( 子查询)
-- S>ALL R:当S大于子查询R中的每一个值,该条件为真TRUE。
-- NOT S>ALL R:当且仅当S不是R中的最大值,该条件为真TRUE
-- ANY确定给定的值是否满足子查询或列表中的部分值。
-- 语法如下: WHERE比较运算符[ NOT ] ANY ( 子查询)
-- S>ANY R:
-- 当且仅当S至少大于子查询R中的一个值,该条件为真TRUE。
-- NOT S>ANY R:
-- 当且仅当S是子查询R中的最小值,该条件为真TRUE。
-- “in”等同于“=any”、not in等同于“<>all”
-- 52、 查询 “清华大学出版社”图书中的价格最高的图书详细信息。
select * from 图书详情 where 价格 in (select MAX(价格) from 图书详情 where 出版社 = '清华大学出版社');
select * from 图书详情 where 价格 in (select MAX(价格) from 图书详情 where 出版社 = '清华大学出版社');
select * from 图书详情 where 出版社 = '清华大学出版社' and 价格 >= all (select 价格 from 图书详情 where 出版社 = '清华大学出版社');
select * from 图书详情 where 出版社 = '清华大学出版社' and 价格 >= all (select 价格 from 图书详情 where 出版社 = '清华大学出版社');
-- 53、 查询比所有“清华大学出版社”图书的价格都低的图书详细信息。
select * from 图书详情 where 价格 < all (select 价格 from 图书详情 where 出版社 = '清华大学出版社');
select * from 图书详情 where 价格 < all (select 价格 from 图书详情 where 出版社 = '清华大学出版社');
-- 54、 查询比任何一个“清华大学出版社”图书的价格低的图书详细信息。
select * from 图书详情 where 价格 < any (select 价格 from 图书详情 where 出版社 = '清华大学出版社');
select * from 图书详情 where 价格 < any (select 价格 from 图书详情 where 出版社 = '清华大学出版社');
-- 55、 查询借阅了“数据库原理”的图书的读者借书证编号、姓名
select 借书证编号, 姓名
from 读者
where 借书证编号 in (select 借书证编号
from 图书详情 tx
left join 图书 t on tx.ISBN = t.ISBN
left join 借阅 jie on t.图书条码号 = jie.图书条码号
where 书名 = '平凡的世界');
select 借书证编号, 姓名
from 读者
where 借书证编号 in (select 借书证编号
from 图书详情 tx
left join 图书 t on tx.ISBN = t.ISBN
left join 借阅 jie on t.图书条码号 = jie.图书条码号
where 书名 = '平凡的世界');
-- 56、 查询借阅图书最积极的读者详细信息
select * from 读者
where 借书证编号 in
(select 借书证编号 from 借阅 group by 借书证编号 having count(*) >= all (select count(*) from 借阅 group by 借书证编号));
select * from 读者
where 借书证编号 in
(select 借书证编号 from 借阅 group by 借书证编号 having count(*) >= all (select count(*) from 借阅 group by 借书证编号));
-- 相关子查询:
-- 57、 查询价格比该书所在出版社所有图书的平均价格低的图书ISBN、书名、价格。
select ISBN, 书名, 价格
from 图书详情
where 价格 < all (select avg(价格) from 图书详情 where 出版社 in (select 出版社 from 图书详情 where 书名 = '平凡的世界'));
select ISBN, 书名, 价格
from 图书详情
where 价格 < all (select avg(价格) from 图书详情 where 出版社 in (select 出版社 from 图书详情 where 书名 = '平凡的世界'));
-- 带有EXISTS的子查询(存在性测试)
-- 58、 查询所有借阅了图书条码号为0000001的读者姓名。
select 姓名
from 读者
where exists(select 借书证编号 from 借阅 where 图书条码号 = '0000001' and 借阅.借书证编号 = 读者.借书证编号);
select 姓名
from 读者
where exists(select 借书证编号 from 借阅 where 图书条码号 = '0000001' and 借阅.借书证编号 = 读者.借书证编号);
-- 用作查询语句中的列表达式的子查询
-- 59:查询图书的ISBN、书名、价格,价格与所有图书平均价格的差值。
select ISBN, 书名, 价格 - (select round(avg(价格)) from 图书详情) from 图书详情;
select ISBN, 书名, 价格 - (select round(avg(价格)) from 图书详情) from 图书详情;
-- 子查询结果作为主查询的查询对象
-- (选做)60:查询有两个以上读者的借阅图书数超过3本的部门
select 部门, COUNT(distinct 借书证编号) tushu
from 读者
group by 部门
having tushu > 3;
select 部门, COUNT(distinct 借书证编号) tushu
from 读者
group by 部门
having tushu > 3;
select 部门 from 读者 group by 部门 having count(distinct 借书证编号) > 3;
select 部门 from 读者 group by 部门 having count(distinct 借书证编号) > 3;
-- INSERT语句中使用SELECT子句
-- 61、 创建“图书”表的一个副本“图书2”,将馆藏地编号为';0001';的图书信息添加到“图书2”,并显示表中内容。
create table 图书2 as select * from 图书 where 馆藏地编号 = '0001';
insert into 图书2 select * from 图书 where 馆藏地编号 = '0001';
create table 图书2 as select * from 图书 where 馆藏地编号 = '0001';
insert into 图书2 select * from 图书 where 馆藏地编号 = '0001';
-- UPDATE语句中使用SELECT子句
-- 62、 将喻明远借阅的“0000001”图书的归还日期修改为“2020-9-1”
update 借阅
set 归还日期 = '2020-9-1'
where 归还日期 in (select 归还日期 from 读者 where 姓名 = '喻明远' and 图书条码号 = '0000001');
update 借阅
set 归还日期 = '2020-9-1'
where 归还日期 in (select 归还日期 from 读者 where 姓名 = '喻明远' and 图书条码号 = '0000001');
-- 63、 将图书表中价格最高图书的价格的减去20。
update 图书详情
set 价格 := 价格 - 20
where 价格 in (select 价格 from (select max(价格) from 图书详情) temp);
update 图书详情
set 价格 := 价格 - 20
where 价格 in (select 价格 from (select max(价格) from 图书详情) temp);
-- 64、 将价格排在前5名的图书的价格减去20。
update 图书详情
set 价格 = 价格 - 20
where 价格 in (select 价格 from (select 价格 from 图书详情 order by 价格 desc limit 5) temp);
update 图书详情
set 价格 = 价格 - 20
where 价格 in (select 价格 from (select 价格 from 图书详情 order by 价格 desc limit 5) temp);
-- DELETE语句中使用SELECT子句
-- 65、 删除喻明远借阅的“0000003”图书借阅信息
delete
from 借阅
where 图书条码号 = (select 图书条码号
from (select 读者.*
from 读者,
借阅
where 借阅.借书证编号 = 读者.借书证编号
and 图书条码号 = '0000003'
and 姓名 = '喻明远') temp);
delete
from 借阅
where 图书条码号 = (select 图书条码号
from (select 读者.*
from 读者,
借阅
where 借阅.借书证编号 = 读者.借书证编号
and 图书条码号 = '0000003'
and 姓名 = '喻明远') temp);
-- 数据查询综合练习
-- 66、 查询还可以继续借阅图书的读者
select * from 读者 where 借书证编号 not in (select 借书证编号 from 借阅);
select * from 读者 where 借书证编号 not in (select 借书证编号 from 借阅);
-- 67、 查询最热门的图书
select * from 图书详情 where ISBN = (select ISBN from 图书 group by ISBN having count(ISBN) order by ISBN limit 1);
select * from 图书详情 where ISBN = (select ISBN from 图书 group by ISBN having count(ISBN) order by ISBN limit 1);
-- 68、 查询借阅超期的读者信息及其借阅信息
-- 69、 查询所有“python”相关图书信息
-- 70、 将一新图书信息进行入库操作
-- 十、 备份、还原数据库
-- 71. 备份book数据库到e盘的mybook.sql文件(备份文件中要求包含建库命令)
cmd命令窗口输入
# mysqldump -uroot -p197412xukang --databases book > E:/mybook.sql
# mysqldump -uroot -p197412xukang --databases book > E:/mybook.sql
-- 72. 使用mysql命令利用e盘根目录的文件“mybook.sql”还原数据库
# mysql -uroot -p197412xukang < E:/mybook.sql
# mysql -uroot -p197412xukang < E:/mybook.sql
-- 十一、 索引
-- 73. 在读者表的姓名列上创建一个降序索引”reader_name_index”
create index reader_name_index on 读者(姓名 desc);
create index reader_name_index on 读者(姓名 desc);
-- 74. 在读者表的部门和姓名上创建一个复合索引”reader_index”
create index reader_index on 读者(部门, 姓名);
create index reader_index on 读者(部门, 姓名);
-- 75. 删除读者表的索引”reader_index”
drop index reader_index on 读者;
drop index reader_index on 读者;
show index from 读者;
show index from 读者;
-- 十二、 视图
-- 76. 创建视图view_reader_book,包括读者的姓名、借书证编号、部门、图书条码号、书名、价格、出版社、馆藏地、借出日期、归还日期
create or replace view view_reader_book as
select 姓名,
读者.借书证编号,
部门,
借阅.图书条码号,
书名,
价格,
出版社,
图书.馆藏地编号,
借阅.借出日期,
借阅.归还日期
from 读者
join 借阅 on 读者.借书证编号 = 借阅.借书证编号
join 图书 on 借阅.图书条码号 = 图书.图书条码号
join 图书详情 图 on 图书.ISBN = 图.ISBN;
select * from view_reader_book;
create or replace view view_reader_book as
select 姓名,
读者.借书证编号,
部门,
借阅.图书条码号,
书名,
价格,
出版社,
图书.馆藏地编号,
借阅.借出日期,
借阅.归还日期
from 读者
join 借阅 on 读者.借书证编号 = 借阅.借书证编号
join 图书 on 借阅.图书条码号 = 图书.图书条码号
join 图书详情 图 on 图书.ISBN = 图.ISBN;
select * from view_reader_book;
-- 77. 利用view_reader_book视图查询部门为"信息工程学院"的读者借阅书籍信息。
select * from view_reader_book where 部门 = '信息工程学院';
select * from view_reader_book where 部门 = '信息工程学院';
-- 十三、 存储过程
-- 78. 创建无参存储过程proc_reader,查询所有读者信息。
create procedure proc_reader()
begin
select * from 读者;
end;
create procedure proc_reader()
begin
select * from 读者;
end;
-- 79. 执行存储过程proc_reader
call proc_reader();
call proc_reader();
-- 80. 创建存储过程pro_reader_info,根据读者的姓名查询读者信息。
create procedure pro_reader_info(in name varchar(10))
begin
select * from 读者 where 姓名 = name;
end;
create procedure pro_reader_info(in name varchar(10))
begin
select * from 读者 where 姓名 = name;
end;
-- 81. 执行存储过程pro_reader_info,查询读者姓名为”俞心怡”的读者信
call pro_reader_info('俞心怡');
call pro_reader_info('俞心怡');
select 图书条码号 from 借阅 where 借书证编号 = '90041011000006';
-- 82. 创建存储过程proc_update,修改某读者借阅的某图书的归还时间
create procedure proc_update(in endTime datetime, in Borrowing_card_number varchar(20), in Book_barcode_number varchar(20))
begin
update 借阅
set 归还日期 = endTime
where 借书证编号 = Borrowing_card_number and 图书条码号 = Book_barcode_number;
end;
drop procedure if exists proc_update;
create procedure proc_update(in endTime datetime, in Borrowing_card_number varchar(20), in Book_barcode_number varchar(20))
begin
update 借阅
set 归还日期 = endTime
where 借书证编号 = Borrowing_card_number and 图书条码号 = Book_barcode_number;
end;
drop procedure if exists proc_update;
存储过程被创建后,就会一直保存在数据库服务器上,直至被删除。当 MySQL 数据库中存在废弃的存储过程时,我们需要将 中删除。
废弃的存储过程
什么是废弃的
已经运行完了的
https://www.cnblogs.com/ccstu/p/12182933.html(MySQL之存储过程procedure)
-- 83. 执行存储过程proc_update ,将“90041011000006”号读者借阅的“0000002”号图书的归还时间修改为“2020-10-1”
call proc_update('2020-10-1', '90041011000006','0000002');
call proc_update('2020-10-1', '90041011000006','0000002');
-- 十四、条件和处理程序
-- 84. 创建错误处理程序,完成以下功能:如果没有更多的行要提取,将no_row_found变量的值设置为1并继续执行。
# Declare continue handler for NOT FOUND set @no_row_found = 1;
-- 85. 创建错误处理程序,完成以下功能:如果发生错误,回滚上一个操作,发出错误消息,并退出当前代码块。如果在存储过程的begin......end块中声明它,则会立即终止存储过程。
# Declare exit handler for SQLEXCEPTION
# begin
# rollback;
# select '发生错误,回滚上一个操作';
# end;
-- 86. 创建错误处理程序,完成以下功能:如果发生重复的键错误,则会发出mysql错误1062,它发出错误消息退出或者继续执行。
# (提示:(1)创建一个数据表t1,只有一个字段id,并且id为主键。
create table t1(id int primary key);
create table t1(id int primary key);
# (2)创建一个存储过程handlerdemo,在存储过程中:插入两次相同的数据,定义处理程序,遇到重复值错误就退出(重复值错误的代码是1062)。
# 第一次插入数据前将用户变量@x设置为1,第一次插入数据之后将@x变量设置为2,第二次插入数据之后将@x变量设置为3。
create procedure handlerdemo()
begin
-- continue 遇到错误继续执行
-- exit 遇到错误退出
declare continue handler for 1062 set @info = '重复键错误';
set @x = 1;
INSERT INTO t1 values (1);
set @x = 2;
INSERT INTO t1 values (1);
set @x = 3;
select @x;
end;
create procedure handlerdemo()
begin
-- continue 遇到错误继续执行
-- exit 遇到错误退出
declare continue handler for 1062 set @info = '重复键错误';
set @x = 1;
INSERT INTO t1 values (1);
set @x = 2;
INSERT INTO t1 values (1);
set @x = 3;
select @x;
end;
# (3)执行存储过程,查询@x变量的值。(4)再次执行存储过程,查询@x变量的值。
call handlerdemo();
select @x;
# (5)删除数据表、删除存储过程,重复(1)-(4)步骤,但把步骤(2)中的处理程序改成遇到重复值错误继续。)
drop table t1;
drop procedure if exists handlerdemo;
drop table t1;
drop procedure if exists handlerdemo;
-- 十五、 游标
-- 87. 利用游标,遍历读者表的所有记录的借书证号、姓名并显示。
delimiter ;
drop procedure if exists cursor_for;
create procedure cursor_for()
begin
declare card_number varchar(50);
declare name varchar(50);
declare count int default 0;
declare u_cursor cursor for (select 借书证编号, 姓名 from 读者);
declare exit handler for not found close u_cursor;
# 开启游标
open u_cursor;
www:while true do
-- 如果获得的数据大于三就退出
if count > 3 then
leave www;
end if;
fetch u_cursor into card_number, name;
select card_number, name;
set count := count + 1;
end while www;
close u_cursor;
end;
call cursor_for();
delimiter ;
drop procedure if exists cursor_for;
create procedure cursor_for()
begin
declare card_number varchar(50);
declare name varchar(50);
declare count int default 0;
declare u_cursor cursor for (select 借书证编号, 姓名 from 读者);
declare exit handler for not found close u_cursor;
# 开启游标
open u_cursor;
www:while true do
-- 如果获得的数据大于三就退出
if count > 3 then
leave www;
end if;
fetch u_cursor into card_number, name;
select card_number, name;
set count := count + 1;
end while www;
close u_cursor;
end;
call cursor_for();
-- 十六、 流程控制
-- 88. 创建存储过程,求1+2+3+......的和,如果和大于100则跳出循环
create procedure p10(in n int)
begin
declare total int default 0;
sum:loop
if total > 100 then
leave sum;
end if;
if n >= 0 then
set total := total + n;
set n := n - 1;
end if;
end loop;
select total;
end;
call p10(100);
-- 十七、 事件
-- 89. 创建在某一时间(时间自己定)执行的事件:在sc表中插入一条数据
-- 十八、 触发器
drop trigger if exists BookUpdate;
show create table 借阅;
alter table 借阅 add constraint fk_cardNumber_bookNumber foreign key 借阅(图书条码号) references 图书(图书条码号);
alter table 借阅 drop foreign key fk_cardNumber_bookNumber;
-- 90. 创建触发器BookUpdate,当图书表的某图书的图书条码号更新时,级联更新借阅表的相应记录图书条码号
create trigger BookUpdate
after update on 图书 for each row
begin
update 借阅 set 借阅.图书条码号 = new.图书条码号 where 借阅.图书条码号 = OLD.图书条码号;
end;
create trigger BookUpdate
after update on 图书 for each row
begin
update 借阅 set 借阅.图书条码号 = new.图书条码号 where 借阅.图书条码号 = OLD.图书条码号;
end;
update 图书 set 图书条码号 = '0000040' where ISBN = '978-754-462-1';
-- 91. 创建触发器BookDelete,当图书表的某图书记录删除时,级联删除借阅表的相应图书借阅记录
create trigger BookDelete
before delete on 图书 for each row
begin
delete from 借阅
where 借阅.图书条码号 = OLD.图书条码号;
end;
delete from 图书 where 图书条码号 = '0000015';
-- 92. 按照“读者”表的结构创建备份表reader_bak,然后在“读者”表中创建触发器insert_reader,每次向“读者”表中插入记录时,自动将插入的记录备份到备份表reader_bak中。
CREATE TABLE reader_bak LIKE 读者;
create trigger insert_reader
after insert on 读者 for each row
begin
insert into reader_bak
select * from 读者 where 读者.借书证编号 = new.借书证编号;
end;
CREATE TABLE reader_bak LIKE 读者;
create trigger insert_reader
after insert on 读者 for each row
begin
insert into reader_bak
select * from 读者 where 读者.借书证编号 = new.借书证编号;
end;
-- 十九、 用户、权限
-- 93. 创建名为user1的用户,密码为user1111,主机名为localhost。
create user 'user1'@'localhost' identified by 'user1111';
create user 'user1'@'localhost' identified by 'user1111';
-- 94. 授予user1@localhost用户对book数据库的select、update 的权限
GRANT select, update on book.* to 'user1'@'localhost';
GRANT select, update on book.* to 'user1'@'localhost';
show grants for 'user1'@'localhost';
drop user if exists 'user1'@'localhost';