MySql 存储过程,触发器,索引,函数
一、存储过程 procedore
1、简介:存储过程是数据库中的一个对象,存储在服务端,用来封装多条SQL语句且带有逻辑性,可以实现一个功能,由于他在创建时,就已经对SQL进行了编译,所以执行效率高,而且可以重复调用,类似与我们Java中的方法。
2、语法:
delimiter $$ -- 将java里的 ";"这个定界符 换为了 "$$"
create procedure show_student() --存储过程的名称
begin
语句
end $$
delimiter; -- 存储过程定义完之后 恢复原来的 定界符 ";"
-- 注意:创建存储过程需要管理员分配权限
3、举例:
ELIMITER $$
CREATE
PROCEDURE `test`.`show_student`()
BEGIN
UPDATE t_student SET atu_age='18' WHERE atu_name='王五';
SELECT * FROM t_student WHERE atu_age='18';
END$$
DELIMITER ;
4、常用方法:
-- 调用存储过程
call show_student;
-- 删除存储过程
drop procedure show_student; ### drop删除
-- 查看所有存储过程的状态
show procedure status;
-- 查看存储过程语句
show create procedure 存储过程名字;
5、带有参数的存储过程:
(1)参数类型:
in 输入参数
out 输出参数
inout 输入输出参数
(2)输入举例:
delimiter $$
-- 创建存储过程并给它 in(输入) int类型的id
create procedure myProcedure1(in id int);
--begin 开始语句
begin
select * from t_user where user.id = id ;
--结束语句 注意:end 后必须加$$
end$$
delimiter;
调用存储过程:
call myProcedure(2);
(3)输出举例:
delimiter $$
-- 创建存储过程并给它 out(输出) varchar类型的str
create procedure myProcedure2(out str varchar(20))
--begin 开始语句
begin
--给str赋值
set str = 'hello';
end$$
delimiter;
调用存储过程:
--调用时候接收带回来的值,用一个@代表零时变量。
call myProcedure1(@r);
--查看
select @r;
6、动态语句
(1)if :
delimiter $$
create procedure mypro(in num int,out result char(32))
begin
if num = 1 then
set result='星期一';
else if num = 2 then
set result='星期二' ;
end if;
end$$;
delimiter;
(2)while(常用):
delimiter $$
create procedure (in num int,out result int)
begin
--定义局部变量 i、sum,初始值为 0、1
declare i int default 1;
declare sum int default 0;
while(i<=num) do
set sum=sum+i;
set i=i+1;
end while;
set result=sum;
end$$
delimiter ;
存储过程优点:
1、存储过程增强了SQL语言灵活性。 存储过程可以使用控制语句编写,可以完成复杂的判断和较复杂的运算,有很强的灵活性;
2、减少网络流量,降低了网络负载。 存储过程在数据库服务器端创建成功后,只需要调用该存储过程即可,而传统的做法是每次都将大量的SQL语句通过网络发送至数据库服务器端然后再执行;
3、存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。
4、系统管理员通过设定某一存储过程的权限实现对相应的数据的访问权限的限制,避免了非授权用户对数据的访问,保证了数据的安全。
二、触发器 trigger
1.简介:监视某种情况,并触发某种操作。
是一个特殊的 存储过程,他的执行不由程序调用,也不是手工启动,他的启动由事件触发。触发器经常用于加强 数据的 完整性约束 和 业务规则。5
在 mysql,触发器可以带你执行 insert,update,delete时执行一些特定的操作。
2.触发器语法四要素:a.监视地点(table);
b.监视事件(insert,update,delete)
c.触发时间(after,before)
d.触发事件(insert,update,delete)
3.语法:
create trigger 名字 (after/before) (insert/update/delete)
on 表名 for each row #这句话是固定的
begin
#需要执行的sql语句
end
注意1:after/before: 只能选一个 ,after 表示 后置触发, before 表示前置触发
注意2:insert/update/delete:只能选一个
4、举例:
创建两张表,商品表和订单表:
#商品表
create table goods(
id int primary key auto_increment,
name varchar(20), -- 商品名
num int -- 商品数量
);
#订单表
create table order_table(
oid int primary key auto_increment,
gid int, -- 订单号(商品id)
much int -- 订单数量
);
添加3条商品数据:
insert into goods(name,num) values('商品1',10),('商品2',10),('商品3',10);
如果我们在没使用触发器之前:假设我们现在卖了3个商品1,我们需要做两件事
(1)往订单表插入一条记录:
insert into order_table(gid,much) values(1,3);
(2)更新商品表中商品1的剩余数量:
update goods set num=num-3 where id=1;
(3)现在我们来创建一个触发器:
-- tg1 触发器名字 after 后置触发
下边这句sql 表示的就是在增加之后 我们要 后置触发 执行的 update语句
DELIMITER $$
CREATE TRIGGER tg1 AFTER INSERT ON `by1909`.order_table FOR EACH ROW
BEGIN
UPDATE goods SET num = num -3 WHERE id = 1;
END $$
DELIMITER;
(4)执行下面的操作,观察两个表的变化:
insert into order_table(gid,much) values(1,3);
会发现商品id为1的(num)数量变成了7,说明我们在插入一条订单时,触发器帮我们自动更新了操作。
5、带有参数的触发器:
(1)对于insert而言,新插入的行用new来表示,行中的每一列的值用new.列名来表示。
完善之后的触发器为:
DELIMITER $$
create trigger tg2 after insert on `by1909`.order_table for each row
begin
update goods set num = num -new.much where id = new.gid;
end $$
DELIMITER;
(2)对于delete而言:原本有一行,后来被删除,想引用被删除的这一行,用old来表示,old.列名可以引用被删除的行的值。
那我们的触发器就该这样写:
DELIMITER $$
create trigger tg2 after insert on `by1909`.order_table for each row
begin
update goods set num = num +old.much where id = old.gid; (注意这边的变化)
end $$
DELIMITER;
6、存储过程 与 触发器 有什么区别呢?
(1)返回值
储存过程没有返回值
触发器本身没有返回值,不过它们可以读取或者改变触发 SQL 语句所影响的数据
(2)调用方法
储存过程 call 方法名(参数)
触发器关系表的执行增删改sql语句时触发
三、索引
1、简介:索引相当于图书的目录,可以帮助用户快速找到想要的内容
数据库利用各种各样的快速定位技术,能够大大提高查询效率。特别是当数据量非常大,查询涉及多个表时,使用索引往往能使查询速度加快成千上万倍.
2、索引的优点:可以提高查询效率,且数据量越大越明显。
索引的缺点:添加效率和删除效率低
3、索引的使用原则:
(1)对经常更新的表就避免对其进行创建过多的索引,对经常用于查询的字段应该创建索 引。
(2)数据量小的表最好不要使用索引,因为由于数据较少,可能查询全部数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果。
(3)在一些值少的列上(字段上)不要建立索引,比如在学生表的"性别"字段上只有男,女两个不同值。相反的,在一个字段上不同值较多可以建立索引。
4、索引的类型: 网址 https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
二叉树:Binary Search Trees
红黑树:Red-Blcak Trees
B-TREE:B-TREE
B+TREE:B+TREE
常见的索引的特点:
(1)二叉树:通过key—value,子节点从左到右依次递增。
缺点:当数据出现单边增长的情况时,索引起不了啥作用,不会自动均衡排序。
任意找两组数据进行测试{1,2,3,4,5,6,7,8,9}和{5,6,4,7,1,2,3,9,8},按顺序输入,得到的效果图:
(2)红黑树:又叫平衡二叉树 ,它自动平衡了单列递增的节点,降低了树的高度。
缺点:当数据量较多时,会大大降低查找的效率。
举例:{5,6,4,7,1,2,3,9,8}
(3)HASH表 :hash就是一种(key=>value)形式的 键值对 类似于map(key,value),允许多个key对应相同的value,但不允许一个key对应多个value,为某一列或几列建立hash索引,就会利用这一列或几列的值通过Hash算法计算出一个hash值,对应一行或几行数据. hash索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率.
任何数据只要走Hash索引,只需经过一次运算,就可通过相应指针找到对应数据Hash基本不用了解即可。(Hash不支持范围查找)
(4)B-TREE: 就是一种将索引值按一定的算法,存入一个树形的数据结构中. 如二叉树一样
引入原理:增加可限度的横向节点,从而大大降低树的高度(若横行节点增加过多,会增加内存消耗)
测试:{1,2,3,4,5,6,7,8,9}:
(5)B+TREE:(B-TREE的变种),在叶子节点下多了一个箭头,双向查询:
测试:{1,2,3,4,5,6,7,8,9}:
注释:
根节点 处在树的最顶端(没有双亲)的结点叫根结点.
叶子结点 就是度为0的结点,就是没有孩子结点的结点。简单的说就是一个二叉树任意一个分支上的终端节点
5、索引的分类:
普通索引
唯一索引
主键索引
组合索引
FULLTEXT:全文索引
全文索引,目前只有MyISAM引擎支持,而且只有Char,Varchar,Text 列上可以创建全文索引.MyISAM不支持事务,支持表锁。
InnoDB支持事务,有行锁,查询性能相对比MyISAM低。
常见的存储引擎有 :InnoDB,MyISAM,一般用的是InnoDB,这里要注意:存储引擎是对数据库表的操作,不是对数据库的操作。
FULLTEXT索引是按照分词原理建立索引的。西文中,大部分为字母文字,分词可以很方便的按照空格进行分割。但很明显,中文不能按照这种方式进行分词。Mysql的中文分词插件Mysqlcft,有了它,就可以对中文进行分词
1.创建 普通索引
1 CREATE index aaa on ren(p_name)
2 添加 普通索引--Normal
3 注意:index :表示索引
aaa:表示索引的别名,
on:表示给哪个表添加索引
ren:表名称,(添加索引的字段,多个字段以","间隔)
2.创建 唯一索引
1 CREATE UNIQUE index aaa on ren(p_age)
2 添加 唯一索引 --UNIQUE index
3 注意:unique index :表示唯一索引
aaa:表示索引的别名,
on:表示给哪个表添加索引
ren:表名称,(添加索引的字段,多个字段以","间隔)
3.创建 主键索引
1 alter table 表名 add primary key(id);
2 添加主键索引
3 注意:主键索引只能有一个 将相当于我们创建表时将id 设为主键
4.创建 组合索引
create index index_name_age on t_user(user_name,user_age);
5.删除索引
删除索引可以使用ALTER TABLE或DROP INDEX语句来实现。DROP INDEX可以在ALTER TABLE内部作为一条语句处理
drop index 索引名 on 表名;
alter table 表名drop index 索引名;
alter table 表明 drop primary key ;
使用情况:
什么情况需要创建索引;
1,主键自动建立唯一索引;
2,频繁作为查询条件的字段应该创建索引;
3,查询中与其它表关联的字段,外键关系建立索引;
4,频繁更新的字段不适合创建索引;
5,where条件里用不到的字段,不要创建索引;
6,单值/复合索引的选择问题,(在高并发的下倾向于创建组合索引);
7,查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度;
8,查询中统计或者分组的字段;
什么情况下不要创建索引:
1,表记录太少;
2,经常增删改的表;
3,数据重复且分布平均的表字段,(比如性别只有男女,那就没必要创建索引);
where name='' and age = 10 and sex = 1,索引能够使用,(全值匹配我最爱。)
where name='' and sex=1;索引能不能使用到?也能使用到,但是只有name能够使用到。(中间兄弟不能断)
where age = 10 and sex=1;索引不能使用到。(带头大哥不能死)
6:索引失效
复合索引,左边的字段,不能少(最佳左前缀法)
不在索引列上做任何操作(计算,函数,(自动或者手动)类型装换),会导致索引失效而导致全表扫描
范围之后索引失效。(< ,> between and)
mysql使用不等于(!= 或者<>)的时候,无法使用索引,会导致索引失效
mysql中like查询是以%开头,索引会失效变成全表扫描,覆盖索引。 把% 写在右边;
mysql中,如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
四、函数
1.简介:mysql中的函数与存储过程类似,都是一组SQL集;
2.与存储过程的区别:
函数可以return值,存储过程不能直接return,但是有输出参数可以输出多个返回值;
函数可以嵌入到sql语句中使用,而存储过程不能;
函数一般用于实现较简单的有针对性的功能(如求绝对值、返回当前时间等),存储过程用于实现复杂的功能(如复杂的业务逻辑功能);
3.mysql自带函数:之前学习到的聚合函数 如:Avg求平均值,Sum求和 等等
4.自定义函数:
1)自定义函数
create function 函数名([参数列表]) returns 数据类型
-- 不带参传递函数
delimiter $$
create function myselect3() returns int
begin
declare c int;
select id from `test`.student where name="李四" into c;
return c;
end $$;
delimiter ;
-- 带传参的函数 参数列表的格式是: 变量名 数据类型
delimiter $$
create function myselect4(names varchar(15)) returns int
begin
declare c int;
select id from `test`.student where name=names into c;
return c;
end $$;
delimiter ;
select myselect4("张三");
2)调用自定义函数
-- 调用查看
select myselect3(); ## 无参调用
select myselect4("张三"); ## 传参调用
--在sql语句中使用自定义函数
select myFun(参数1,参数2),name from 表名
3)删除自定义函数
drop function myselect3;
4)查看函数
查看函数创建语句:show create function 函数名;
查看所有函数:show function status;
5)修改函数
函数的修改只能修改一些如comment的选项,不能修改内部的sql语句和参数列表。
alter function 函数名 选项;
存储过程,触发器,函数三者之间的关系
调用方法:
储存过程 直接用call 储存过程名(),括号里可以传递参数
触发器 执行关系表中的增删改sql语句时触发
函数 select 函数名(),括号里可以传递参数
返回值类型:
储存过程 无返回值
触发器 触发器本身没有返回值,不过它们可以读取或者改变触发 SQL 语句所影响的数据
函数 有返回值类型
如需要详细资料(免费),请加入QQ群:920199935