-- 九、 子查询
 -- 无关子查询
 -- 比较子查询:能确切知道子查询返回的是单值时,可以用>,<,=,>=,<=,!=或<>等比较运算符。
 -- 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';
  



















