mysql优化课之mysql基础,视图触发器存储过程

mysql基础,视图触发器存储过程


目录php

  • mysql基础,视图触发器存储过程
    • 概念
    • 建立存储过程
    • 存储过程的理解
    • 变量
    • 存储过程的数据类型
    • 流程控制
    • 游标
    • 存储过程的优势
    • 存储过程的缺点
    • 小结
    • 语法
    • 总结
    • 概念
    • 建立触发器
    • 查看触发器
    • 使用的注意事项&产生的问题以及好处
    • 建立触发器的语法:
    • 注意事项
    • 产生的问题
    • 触发器的好处
    • 概念
    • 建立一个视图
    • 查看视图
    • 视图的优缺点
    • 视图的UID
    • 如下是视图不可更新的状况
    • 视图的做用&好处
    • desc查看视图结构
    • select来查看
    • 优势
    • 缺点
    • 例子
    • 课程内容
    • 上节课内容
    • mysql视图基础
    • mysql触发器
    • mysql存储过程


课程内容

上节课内容

mysql视图基础

概念

  1. 视图是MySQL在5.0.1版本中加入的功能.它能够理解为一个虚表.mysql

  2. 之因此被称为虚表,是由于它只是存储了一个结构,并不存储真实的数据.
    行和列的数据来自定义视图的查询中使用的表,而且是在使用视图时动态生成
    的,只保存了sql逻辑,不保存查询结果.程序员

  3. 视图并非真的优化web

建立一个视图

--建立视图的语法:sql

create view 视图名称 as select语句;

--建立一个视图数据库

create view user_view as select id,name,age,sex from user;

查看视图

查看视图的方式和表同样能够经过select来查看,desc查看视图结构编程

desc查看视图结构

select来查看

注意:视图查询的数据实则来自于源数据中的内容.而它本质只是存储了一个结构,并非存储真实的数据缓存

好比:PHP当中封装了一个查询的方法安全


视图的优缺点

优势

1. 第一个显著优势就是它简化了操做.
   此时咱们彻底不用关心视图是怎么处理数据的,
   咱们只须要知道如何使用这个结果集便可,视图至关于一个中间层. 
2. 第二个显著优势就是它更加安全.
   好比咱们可让用户有权去访问某个视图,可是不能访问原表,
   这样就能够起到保护原表中某些数据的做用. 
3. 咱们以后会接触到管理权限,权限是没法细致到某一个列的,经过视图,则很容易实现. 
4. 第三个显著优势就是下降耦合.假如咱们之后要修改原表的结构,那么咱们能够经过修改视图的定义便可,
   而不用修改应用程序,对访问者是不会形成影响 的,通常来讲,这样代价会更小.

缺点

1. 性能:从数据库视图查询数据可能会很慢,特别是若是视图是基于其余视图建立的. 
2. 表依赖关系:将根据数据库的基础表建立一个视图.每当更改与其相关联的表的结构时,都必须更改视图.

视图的UID

表的数据是能够修改与更新的,可是在视图就不必定了.服务器

--修改视图字段的值会直接修改到源数据表 
update `user_view` set name='小哈' where id=1; select * from `user`; 
--删除视图 
drop view user_view;

如下是视图不可更新的状况

1. 包含聚合函数、distinct、group by、having、union、union all. 
2. 常量视图. 
3. select 包含子查询. 
4. 包含链接操做. 
5. from 一个不能更新的视图. 
6. where 子句的子查询引用了 from 子句中的表.

例子

建立一个视图:

create view user_view_2 as select id,name,age,sex,status from `user` where status=0; 
select * from `user_view_2`;

如今给视图添加一条status=1的数据

insert into `user_view_2`(id,name,age,sex,status)values(11,'小每天',22,'男',1); 
select * from `user_view_2`; 
select * from `user`;

能够发现即便不知足视图的条件也能够插入数据到表里面

with check option

1. 对于上面的表 t2,咱们想:是否能够建立一个视图,它只容许修改知足本视图要求的数据,
   而对于不知足本视图要求的数据操做, 通通拒绝呢?
2. 答案是确定的.那就须要 with check option 了,不过该修饰符还有更加深一步的权限机制. 
3. 首先咱们仍是利用上一步的 t2,咱们建立一个视图 v3,它的建立
drop view `user_view_2`; 
create view user_view_3 as select id,name,age,sex,status from `user` where status=0 with check option;
insert into `user_view_3`(id,name,age,sex,status)values(12,'小灰灰',22,'男',1); 
select * from `user_view_3`;

错误信息

[Err] 1369 - CHECK OPTION failed 'mysql_php.user_view_3'

这里能够理解为 with check option 的做用就是多了一个 check 的功能,即检查的功能,
也就是说插入的数据必须知足该视图的条件,才容许被操做

视图的做用&好处

1.提升了重用性,就像一个函数.若是要频繁获取user的name和goods的name.就应该使用如下sql语言.

示例:

select a.name as username, b.name as goodsname from user as a, goods as b, ug as c where a.id=c.userid and c.goodsid=b.id;

但有了视图就不同了,建立视图other.

示例

create view other as select a.name as username, b.name as goodsname from user as a, goods as b, ug as c where a.id=c.userid and c.goodsid=b.id;

建立好视图后,就能够这样获取user的name和goods的name.

示例

select * from other;

以上sql语句,就能获取user的name和goods的name了.

2.对数据库重构,却不影响程序的运行.假如由于某种需求,须要将user拆房表usera和表userb,该两张表的结构以下:

  测试表:usera有id,name,age字段 
  测试表:userb有id,name,sex字段

这时若是php端使用sql语句:

select * from user;

那就会提示该表不存在,这时该如何解决呢.解决方案:建立视图.如下sql语句建立视图:

create view user as select a.name,a.age,b.sex from usera as a, userb as b where a.name=b.name;

以上假设name都是惟一的.

此时php端使用sql语句:

select * from user;

就不会报错什么的.

这就实现了更改数据库结构,不更改脚本程序的功能 .

3.提升了安全性能.能够对不一样的用户,设定不一样的视图.

例如:某用户只能获取user表的name和age数据,不能获取sex数据.

则能够这样建立视图.示例以下:

create view other as select a.name, a.age from user as a;

这样的话,使用sql语句:

select * from other;

最多就只能获取name和age的数据,其余的数据就获取不了了.

  1. 让数据更加清晰.想要什么样的数据,就建立什么样的视图

mysql触发器

概念

1. 触发器(trigger)是MySQL提供给程序员和数据分析员来保证数据完整性的一种方法. 
2. 它是与表事件相关的特殊的存储过程,它的执行不是由程序调用,也不是手工启动,
   而是由事件来触发,好比当对一个表进行操做(insert,delete, update)时就会激活它执行.

建立触发器

建立触发器的语法:

--触发器建立语法

create trigger [触发器名称] trigger_time trigger_event
on [表名] for each row 
begin 
    trigger_stmt 
end;
  1. trigger_time:指的是触发器的触发时间,能够是 before 或者是 after.其中 before 表示在检查约束前触发,而 after 表示在检查约束后触发.

  2. trigger_event: 是触发器的触发事件,能够是 insert、update、delete.

  3. trigger_stmt:触发事件执行的语句

  4. 对同一个表相同触发时间、相同触发事件的状况下,只能定义一个触发器.

  5. 其中的 for each row 表示是行级触发的,也就是以行为单位.也有数据库支持语句级触发.可是目前对于 MySQL 来讲 for each row 几乎是必须只能这么 写.

  6. 定义一个触发器

--建立一个触发器,用于监视`user`表,只要`user`表新增数据,`test`表同样增长一条数据 
create trigger user_trigger after insert on `user` 
begin
for each row 
insert into `test` (id,name,age,sex,status)values(3,'小哈',22,'男',1); 
end

--向`user`表添加一条id=12的数据 
insert into `user` (id,name,age,sex,status)values(12,'小哈哈',33,'男',1);

--查询`test`表与`user`表的内容 
select * from `test`; 
select * from `user`;

这时触发器的做用就已经体现出来了,在咱们向user中插入数据的时候, test中的数据也会自动随着变化.

查看触发器

若是咱们要查看已经建立的触发器,能够选定某个数据库

--查看选定数据库的触发器 
show triggers \G;

使用的注意事项&产生的问题以及好处

注意事项

1. MySQL触发器能基于行触发,MySQL触发器始终时基于表中的一条记录触发,而不是一组SQL语句.
   所以,若是须要变更整个数据集而数据集数据量又较大 时,触发器效果会很是低. 
2. 每个表的一个事件只能定义一个触发器,例如:不能在AFTER INSERT上定义一个以上的触发器.

产生的问题

产因为MySQL触发器基于行触发的特性,所以对于批量操做并不适合使用触发器,如:汇总表、缓存表等.

触发器使用不当,可能会致使如下问题:

1. 一个MySQL触发器可能会关联到另一张表或几张表的操做.
   所以,会致使数据库服务器负荷也会相应的增长一倍或几倍,若是出现由于触发器问题致使的性能问题,
   会很难定位问题位置和缘由. 
2. 在基于锁的操做中,触发器可能会致使锁等待或死锁.触发器执行失败,原来执行的SQL语名也会执行失败.
   而由于触发器致使的失败结果和失败缘由,往 往很难排查.

因为MySQL触发器的种种问题,要求咱们在建立触发器就应该充分考虑.

避免使用不合适的触发器,并能对全部触发器有足够的了解,以便问题的定位和排查.

触发器的好处

触对MySQL触发器有足够的认识和了解后,MySQL触发器会给咱们带来极大的便利.

当实现一些系统约束时,或在实现系统维护及针对操做数据的更新时,使用 触发器都很是方便.

在之胶咱们介绍了MySQL触发器不适合作的一些工做,但MySQL触发器在如下一些应用场景中,会很是实用:

1. 基于行数据变动的日志记录.
   如:在用户订单系统中,咱们能够基于用户订单数据状态的改变,使用触发器构建用户订单日志表数据. 
2. 基于行数据变动的关系数据的更新.
   如:用户订单改变至付款或相关状态时,咱们能够基于用户订单数据状态的改变,使用触发器改变用户会付款或相应状态信息. 
3. 基于行数据变动的数据汇总.
   如:用户订单成交或失败,咱们能够基于用户订单数据状态的改变,使用触发器构建用户总成交量或失败量汇总数据.

mysql存储过程

概念

1. MySQL 从 5.0 开始支持存储过程. 
2. 存储过程和函数能够理解为一段 SQL 语句的集合,它们被事先编译好而且存储在数据库中. 
3. 在 Pascal 语言中,是有”过程”和”函数”的区分的,过程能够理解为没有返回值的函数.
不过在 C 家族语言中,则没有过程这个概念,统一为函数.

建立存储过程

--存储过程建立语法
create procedure 存储过程名(参数列表)
begin
存储过程体
end

当咱们调用一个存储过程的时候,可使用以下方式:

--调用存储过程的方式 
call 存储过程名(参数列表)

下面建立一个简单的存储过程:

--建立一个存储过程,用于建立t1表 
create procedure user_procedure() 
begin 
    create table t1(id int,name varchar(25)); 
end

--调用存储过程user_procedure 
call user_procedure();

--建立一个能向t1表新增数据的存储过程 
create procedure user_insert_procedure(in x int,in y varchar(25))--in 表示输入 
begin 
    insert into t1 values(x,y); 
end

--调用存储过程user_insert_procedure 
call user_insert_procedure(1,'sixstar');

参数类型

1. 从上面的过程当中咱们了解到存储过程有参数类型这种说法,它的类型能够取值有三个:in、out、inout. 
2. 其中它们的意义以下: 
    (1)in 表示只是用来输入. 
    (2)out 表示只是用来输出. 
    (3)inout 能够用来输入,也能够用做输出.
--建立一个拥有输入与输出变量的存储过程
create procedure user_procedure_out(in x int,out y varchar(25)) 
begin 
    select `name` into y from `t1` where id=x; 
end
--调用存储过程user_procedure_out
call user_procedure_out(1,@a);
--查询输出结果
select @a;

删除存储过程

--删除存储过程语法 drop procedure 存储过程名
drop procedure user_procedure;

存储过程的理解

1. 调用存储过程与直接执行 SQL 语句的效果是相同的,可是存储过程的一个好处是处理逻辑都封装在数据库端. 
2. 当咱们调用存储过程的时候,咱们不须要了解其中的处理逻辑,一旦处理逻辑发生变化,只须要修改存储过程便可,
   对调用它的程序彻底无影响. 
3. 调用存储过程和函数能够简化应用开发人员的不少工做,减小数据在数据库和应用服务器之间的传输,
   能够提升数据处理的效率.

变量

  1. 存储过程当中是可使用变量的,咱们能够经过 declare 来定义一个局部变量,
    该变量的做用域只是 begin....end 块中.

  2. 变量的定义必须写在符合语句的开头,而且在任何其余语句的前面.咱们能够一次声明多个相同类型的变量,
    咱们还可使用default 来赋予默认值.

  3. 定义一个变量的语法为:

declare 变量名 1 [,变量名 2...] 变量类型 [default 默认值]
  1. 上面的变量类型就是 MySQL 支持的类型,而变量名的取值规则也是一个老生常谈的话题了,就不赘述了.

  2. 变量能够直接赋值,还能够经过查询赋值.

  3. 直接赋值就是使用 set 来进行赋值,它的语法为:

set 变量名 1 = 表达式 1 [,变量名 2=表达式 2...]

7.也能够经过查询来将结果赋值给变量,它须要要求查询返回的结果只有一行,语法范例:

select 列名列表 into 变量列表 from 表名 其余语句;

8.定义一个存储过程,练习变量使用

create procedure user_procedure_declare(in x int,out y varchar(25)) 
begin 
    declare s varchar(25); 
    select `name` into s from `t1` where id=x; 
    set y=s; 
end 

call user_procedure_declare(1,@a); 

select @a;

存储过程的数据类型

存储过程当中的数据类型

1. 数值类型:Int,float,double,decimal 
2. 日期类型:timestamp,date,year 
3. 字符串:char,varchar,text
timestamp: 是使用最多的数据类型-》十位数的时间戳 
text:一旦用到text类型的时候就能够考虑分表;

若是部分表的话,该字段的查询不会直接放在一块儿查询,由于多个字段查询中其中若是有text字段的话,
就容易遇到慢查询因此一般的话,若是须要这个值的时候会根据id单独拿这个text字段

流程控制

if 的语法格式为:
if 条件表达式 then 语句 
    [elseif 条件表达式 then 语句] .... 
    [else 语句] 
end if

case 的语法格式
首先是第一种写法:
case 表达式 
    when 值 then 语句 
    when 值 then 语句 ... 
    [else 语句] 
end case
而后是第二种写法:
case 
    when 表达式 then 语句 
    when 表达式 then 语句 .... 
    [else 语句] 
end case

loop 循环语法格式为:
[标号:] loop 
    循环语句 
end loop [标号]

while 
    while a>100 
do
    循环语句 
End while

Repeat //游标
    SQL语句1 UNTIL
    条件表达式 
END Repeat;

Loop
    SQL语句
    全部的条件判断和跳出须要本身实现
End loop

leave语句用来从标注的流程构造中退出,它一般和begin...end或循环一块儿使用leave标号;
 
声明语句结束符,能够自定义: 
DELIMITER [符合]
delimiter $$ $$

游标

1. 游标也有的资料上称为光标. 
2. 咱们能够在存储过程当中使用游标来对结果集进行循环的处理. 
3. 游标的使用步骤基本分为:声明、打开、取值、关闭.

语法

DECLARE test_cursor CURSOR FOR 结果集; //声明游标 
OPEN test_cursor; //打开游标 
CLOSE test_cursor; //关闭游标 
DECLARE CONTINUE HANDLER FOR NOT FOUND //结果集查询不到数据自动跳出

总结

1. 游标的声明的语法:declare 游标名称 cursor for 查询语句; 
2. 打开光标的语法:open 游标名称; 
3. 获取游标数据:fetch 游标名称 into 变量名 1 [,变量名 2 ....] 
4. 关闭游标的语法:close 游标名称;
5. 游标的基本使用须知:对某个表按照循环的处理,判断循环结束的条件是捕获not found的条件,
   当 fetch 光标找不到下一条记录的时候,就会关闭光标然 后退出过程. 
6. 可能有过 Pascal 编程经验的朋友们都会知道,声明的顺序也是很重要的,在SQL中, 
   咱们使用 declare 定义的顺序是:变量、条件、游标、应用程序.

操做查询出来的数据会放置于临时表中,而后再经过游标去读取数据.

存储过程的优势

1. 第一点优点就是执行速度快.由于咱们的每一个SQL语句都须要通过编译,
   而后再运行,可是存储过程都是直接编译好了以后,直接运行便可. 
2. 第二点优点就是减小网络流量.咱们传输一个存储过程比咱们传输大量的 SQL 语句的开销要小得多. 
3. 第三点优点就是提升系统安全性.由于存储过程可使用权限控制,
   并且参数化的存储过程能够有效地防止SQL注入***.保证了其安全性. 
4. 第四点优点就是耦合性下降.当咱们的表结构发生了调整或变更以后,咱们能够修改相应的存储过程,
   咱们的应用程序在必定程度上须要改动的地方就较小了. 
5. 第五点优点就是重用性强.由于咱们写好一个存储过程以后,再次调用它只须要一个名称便可,
   也就是”一次编写,随处调用”,并且使用存储过程也可让程 序的模块化增强.

存储过程的缺点

1. 第一个缺点就是移植性差.由于存储过程是和数据库绑定的,若是咱们要更换数据库之类的操做,可能不少地方须要改动. 
2. 第二个缺点就是修改不方便. 由于对于存储过程而言,咱们并不能特别有效的调试,
   它的一些bug可能发现的更晚一些,增长了应用的危险性. 
3. 第三个缺点就是优点不明显和赘余功能.对于小型web应用来讲,若是咱们使用语句缓存,发现编译SQL的开销并不大,
   可是使用存储过程却须要检查权限一类的开销,这些赘余功能也会在 必定程度上拖累性能.

小结

1. 存储过程和函数的优点是能够将数据的处理放在数据库服务器上进行,
   避免将大量的结果集传输给客户端,减小了数据的传输,所以也减小了宽带和服务器的压力. 
2. 可是在数据库服务器上进行大量的运算也会占用服务器的 CPU,形成数据库服务器的压力. 
3. 通常来讲是不建议在存储过程当中进行大量的复杂的运算的,它们不是数据库服务器的强项,
   咱们应该把这些操做让应用服务器去处理.