1. 存储程序

# 1.存储程序
# 1.1 存储程序:保存和运行在mysql服务中的一个程序
# 1.2 存储程序:
#     1)存储过程
#     2)存储函数
#     3)触发器

# 2.存储过程
# 2.1 存储过程:保存在mysql服务中一段sql语句
# 2.2 创建存储过程:
#          create procedure 存储过程名字(可选的参数列表)
#			   begin 
#              sql语句
#          end;
# 2.3 存储过程中参数分成:输入参数(in 默认) 输出参数(out) 输入输出参数(inout)

# 示例1:固定查询id为2的学生的名字,把该操作定义为存储过程
# 定义无参的存储过程
create procedure getNameById() 
begin 
	select name from stu_info where id=2;
end;
#调用存储过程
call getNameById();

# 示例2:根据学生的id查询学生的名字,把该操作定义为存储过程
# 定义有参的存储过程(输入参数)
create procedure getNameById2(pid int)
begin 
	select name from stu_info where id=pid;
end;
#调用存储过程
call getNameById2(7);

# 示例3:根据学生的id查询学生的名字并且把名字传出来,把该操作定义为存储过程
# 定义有参的存储过程(输入参数,输出参数)
create procedure getNameById3(pid int, out pname varchar(10))
begin 
	#把查询的name通过into关键字存入输出参数中
	select name into pname from stu_info where id=pid;
end;
#调用存储过程
# 说明:@用于在存储过程外面定义变量
call getNameById3(3,@sname);
# 说明:需要在存储过程的外面查询输出参数中的数据
select @sname;

# 示例4:根据学生的id查询学生的年龄并且把年龄传出来,把该操作定义成为存储过程
# 说明:因为id输入参数和age输出参数的类型一致,所以可以考虑用一个inout参数定义
#       定义inout参数的时候,要保证输入参数和输出参数的类型一致
create procedure getAgeById(inout id_age int)
begin 
	select age into id_age from stu_info where id=id_age;
end;
#调用存储过程
set @pid=4;#在存储过程外面给自定义的变量赋值
call getAgeById(@pid);
select @pid;

# 2.4 在存储过程中使用if分支
# 分支结构的语法:

# if 条件 then 
#		分支代码块1
# elseif 条件 then 
#   分支代码块2
# ... ...
# else 
#   分支代码块n
# end if;

# 示例1:根据输入的季节编号输出季节的名称
create procedure seaon(num int)
begin 
	declare sname varchar(5); # 在存储过程中自定义变量
	if num=1 then 
		set sname='春天'; # 给变量赋值
	elseif num=2 then 
    set sname='夏天';
	elseif num=3 then 
    set sname='秋天';
	else 
		set sname='冬天';
	end if;
  #在分支运行完以后查询季节名
  select sname;
end;
# 调用存储过程
call seaon(3);

# 2.5 在存储过程中使用循环结构
# 2.5.1 分类:while  loop  repeat 

# while循环
# 语法:
#		while 条件 do 
#     循环体
#   end while;
# 示例1:创建存储过程实现指定整数以内的数字的输出
create procedure printNum1(num int)
begin 
	declare i int;
	set i=0;
	while i<num do 
		select i;
		set i=i+1;
  end while;
end;
#调用存储过程
call printNum1(5);

# loop循环
# 语法:

#    [自定义的循环名:]loop 
#       循环体
#       (想结束循环用leave 循环名;)
#    end loop;
#
# 示例2:创建存储过程实现指定整数以内的数字的输出
create procedure printNum2(num int)
begin 
	declare i int;
	set i=0;
	myloop:loop 
		select i;
		set i=i+1;
		if i>=num then
			leave myloop;
		end if;
  end loop;
end;
#调用存储过程
call printNum2(5);

# repeat循环
# 语法:

#   repeat 
#			循环体
#     until 循环结束的条件
#   end repeat;

# 示例3:创建存储过程实现指定整数以内的数字的输出
create procedure printNum3(num int)
begin 
	declare i int;
	set i=0;
	repeat 
		select i;
		set i=i+1;
		until i>=num # 此处没有;
  end repeat;
end;
#调用存储过程
call printNum3(5);


# 3.存储函数
# 3.1 存储函数:是保存和运行在mysql服务中的一段程序
#               (可以理解成为能够定义返回值的存储过程)
# 3.2 语法:

#   create function 存储函数名字(形参列表)
#   returns 返回值类型
#   begin 
#        函数体
#        return 返回值;
#   end;

# 示例1:根据学生的id查询学生的名字并且返回
create function findNameById(pid int)
returns varchar(10) # 定义函数的返回值类型
begin 
	declare sname varchar(10);
	select name into sname from stu_info where id=pid;
  return sname; # 返回数据
end;
# 调用存储存储函数
select findNameById(6);

# 4.存储过程和存储函数的区别:
# 1)存储过程不能定义返回值,只能通过输出参数传出数据
# 2)存储函数,只能通过返回值传出数据,并且必须要有返回值
# 3)存储过程就是定义一个功能的实现过程的,所以直接可以调用
# 4)存储函数是用来返回一个结果的,所以存储函数一定要用到sql语句中
# 5)定义的关键字不一样,一个是procedure,一个是function

# 5.存储过程和存储函数的相同点:
# 1)都是保存和运行在mysql服务中的一段程序
# 2)都是可以用来把一些常用的数据库操作事先定义出来,方便后续的使用

# 6.触发器
# 6.1 触发器:监测表的操作的,当表中发生了对应的操作,触发器就会执行。
# 示例1:实现银行系统备份注销用户的信息
# 语法:
#     create trigger 触发器名
#     触发器执行时机 事件类型
#     on 表名 for each row 
#     begin 
#        触发器体
#     end;

# 语法解释:
#      触发器执行时机:before after
#      事件类型:insert update delete
#      for each row :给表中的每一行添加上监测

# 复制bank表的结构,用于存储备份的用户信息
create table bank_tmp select * from bank where 1>10;
# 创建触发器
create trigger tri_bank
after delete 
on bank for each row
begin 
  #把删除的数据保存到备份表中
  #当bank原表中发生了删除事件之后,删除的数据会被触发器拿到,用old对象传入
	insert into bank_tmp values(old.id,old.name,old.pwd,old.money);
end;
# 删除bank表中的一条记录(产生事件)
delete from bank where id=3;

7.	存储程序的优缺点:
   优点:保存和运行在mysql服务中的,所以运行的效率比较高
   缺点:保存于服务中,不便于维护和拓展
         会占据服务的资源,影响系统的运行效率

2. 视图

# 1. 视图
# 1.1 视图:是一张虚拟的数据库表,并不实际存在该张表。
# 1.2 视图的特点:在操作视图的时候,其实是动态的通过操作原表来实现功能。
# 1.3 视图创建的语法:create view 视图名 as 一个sql语句;
# 1.4 通过视图实现crud操作:跟在原表中实现crud的操作一样
# 1.5 限制视图数据的可用性:with check option(通过视图做的修改,必须还能通过视图看到)
# 1.6 删除视图:drop view 视图名;
# 1.7 为什么使用视图:
#       1)使用视图可以保证数据的安全性(不提供银行余额)
#       2)简化开发,提升开发效率(把常用的表连接事先写好,用视图管理)
#       3)定制化数据(可以根据需要,任意的组织数据库中的表形成数据)


# 示例1:查询stu_info表中的所有数据,并创建一个视图管理。
create view stuview as select * from stu_info;

# 示例2:查询部门编号为30的员工的名字和薪水以及部门编号,并创建视图管理
create view empview as select ename,sal,deptno from emp_copy where deptno=30;

# 示例3:通过empview视图,查询'james'的薪水(通过视图查数据,只能查视图管理的数据)
select sal from empview where ename='james';
select sal from empview where ename='king';

# 示例4:通过empview视图,更新'james'的薪水为2000(通过视图修改数据,数据的修改其实是发生在原表)
update empview set sal=2000 where ename='james';

# 示例5: 通过empview视图,插入新员工信息(通过视图插入数据,数据的修改其实是发生在原表)
# 插不进去,原因:视图想要添加的数据,不符合原表的结构要求,(不符合主键不能为null的约束)
insert into empview(ename,sal,deptno) values('kat',3000,20);
# 插不进去,原因:视图管理的字段跟想插入的数据的个数不一致
insert into empview values(76123,'kat','clerk',7566,'1981-02-20 00:00:00',3000,0,20);
# 可以插入(还是插入了原表)
insert into stuview values(9,1808,'kat',21,16785,167576);

# 示例6:通过stuview删除'kat'的信息(通过视图删除数据,还是操作原表)
delete from stuview where name='kat';

# 示例7:通过empview视图把视图中管理的数据的而部门编号改为10
# 没有限制视图的数据的可用性的
update empview set deptno=10; #(修改完以后,empview视图中就没有可管理的数据了)

# 示例8:通过with check option限制视图数据的可用性
# 查询部门编号为30的员工的名字和薪水以及部门编号,并创建视图管理,且保证视图数据的可用性
create view empview1 as select ename,sal,deptno from emp where deptno=30 with check option;
# 限制完以后,在修改部门的编号
update empview1 set deptno=10;# (限制完以后,不让修改,但是通过原表是可以改的)

# 示例9:删除empview视图
drop view empview;

3. 索引

# 1. 索引
# 1.1 索引:用于提升对于表中的数据的查询的效率而设计的一种结构
# 1.2 分类:(根据底层算法原理)
#     1) B-Tree索引
#     2) 全文索引
#     3) 位图索引
# 1.3 B-Tree索引:其实是一中采用B-Tree查找算法实现的索引。
#      查找算法:顺序查找算法(逐一比较)  
#                二分查找(先对数据进行排序,然后把数据按照中间值分成两个区间)
#      基于二分查找算法演化出了一种数据结构---二叉树(任何一个节点的值要大于左子节点,小于右子节点)
#      二叉树(普通二叉树,平衡二叉树)
#      平衡二叉树由普通二叉树衍生的,要求是任何一节点的左子树和右子树的高度差不能超过1
#      平衡二叉树的查询效率要高于普通的二叉树
#      B-tree是基于平衡二叉树衍生的,称为多路平衡二叉树。
#     (MySql数据库使用B+Tree算法实现索引的创建)

# 1.4 查看sql语句的查询效率
explain select * from stu_info where name='tom';

# 1.5 如何添加索引
# create index 索引名 on 表名(字段名);
create index name_index on stu_info(name);
# 验证添加完索引以后的查询效率
explain select * from stu_info where name='tom';

# 1.6 mysql中的索引的分类:普通索引,唯一索引,全文索引,空间索引
# 表中的主键其实默认就添加了唯一索引
explain select * from stu_info where id=6;

# 1.7 删除索引: drop index 索引名;

# 1.8 使用索引需要注意:
#  1)并不是把表中的所有的字段都添加索引。
#     (因为索引在文件中存着,添加数据需要改索引结构,索引太多影响插入,更新,删除的效率)
#  2)如果一个表的插入,更新,删除的频率高于查询,就不太适合添加索引。
#  3)如果表的数据量很小,也不适合添加索引。
#  4)字段的数据量比较小的,该字段也不适合添加索引。

# MyISAM存储引擎:一张表用以下的3个文件存储
#       .frm  表的结构
#       .myi  表的索引
#       .myd  表的数据

#InnoDB存储引擎:一张表用以下的2个文件存储
#       .frm  表的结构
#       .ibd  表的数据和表的索引