视图,触发器,存储过程综合
一、视图
1、什么是视图
视图是一个虚拟表(非真实存在),其本质是【根据SQL语句获取动态的数据集,并为其命名】,用户使用时只需使用【名称】即可获取结果集,可以将该结果集当做表来使用。
2、为什么要用视图
使用视图我们可以把查询过程中的临时表摘出来,用视图去实现,这样以后再想操作该临时表的数据时就无需重写复杂的sql了,直接去视图中查找即可
3、视图特点
- 视图的列可以来自不同的表,是表的抽象和逻辑意义上建立的新关系
- 视图是由基本表(实表)产生的表(虚表)
- 视图的建立和删除不影响基本表
- 对视图内容的更新(添加、删除和修改)直接影响基本表
- 当视图来自多个基本表时,不允许添加,修改和删除数据
创建视图
create view 视图名称 as SQL语句;
使用视图
select * from 视图名称;
更新视图
alter view 视图名称 AS SQL语句;
删除视图
drop view 视图名称;
强调
1、在硬盘中,视图只有表结构文件,没有表数据文件
2、视图通常是用于插叙,尽量不要修改视图中的数据
二、触发器
在满足对某张表数据的增、删、改的情况下,自动触发的功能称之为触发器
为何要用触发器?
触发器专门针对我们对某一张表数据增insert、删delete、改update的行为,这类行为一旦执行
就会触发触发器的执行,即自动运行另外一段sql代码
create trigger tri_after_insert_t1 after/before insert/delete/update on 表名 for each row begin sql代码。。。 end #after 事件执行之后触发 before 事件执行之前触发 #触发事件 insert delete update操作,触发触发器执行 复制代码
CREATE TABLE cmd ( id INT PRIMARY KEY auto_increment, USER CHAR (32), priv CHAR (10), cmd CHAR (64), sub_time datetime, #提交时间 success enum ('yes', 'no') #0代表执行失败 ); CREATE TABLE errlog ( id INT PRIMARY KEY auto_increment, err_cmd CHAR (64), err_time datetime ); delimiter $$ create trigger tri_after_insert_cmd after insert on cmd for each row begin if NEW.success = 'no' then insert into errlog(err_cmd,err_time) values(NEW.cmd,NEW.sub_time); end if; end $$ delimiter ; #当使用update语句的时候,当修改原表数据的时候相对于修改数据后表的数据来说原表中修改的那条数据就是OLD对象, #而修改数据后表被修改的那条数据就是NEW对象 #往表cmd中插入记录,触发触发器,根据IF的条件决定是否插入错误日志 INSERT INTO cmd ( USER, priv, cmd, sub_time, success ) VALUES ('egon','0755','ls -l /etc',NOW(),'yes'), ('egon','0755','cat /etc/passwd',NOW(),'no'), ('egon','0755','useradd xxx',NOW(),'no'), ('egon','0755','ps aux',NOW(),'yes'); #drop trigger tri_after_insert_cmd;
#delimiter $$ 操作用于将结束符号从 ' ;' 改为 ' $$ ' ,用于屏蔽掉触发器中的 ';'
在触发器结尾要加上 delimiter ; ,将结束符再改回来,不影响其他代码的正常执行
三、存储过程
存储过程包含了一系列可执行的sql语句,存储过程存放于MySQL中,通过调用它的名字可以执行其内部的一堆sql。
三种开发模型:
1、 应用程序:只需要开发应用程序的逻辑
mysql:编写好存储过程,以供应用程序调用
优点:开发效率,执行效率都高
缺点:考虑到人为因素、跨部门沟通等问题,会导致扩展性差
2、 应用程序:除了开发应用程序的逻辑,还需要编写原生sql
mysql: 执行sql
优点:比方式1,扩展性高(非技术性的)
缺点:
1、开发效率,执行效率都不如方式1
2、编写原生sql太过于复杂,而且需要考虑到sql语句的优化问题
3、 应用程序:开发应用程序的逻辑,不需要编写原生sql,基于别人编写好的框架来处理数据,ORM
mysql:执行sql
优点:不用再编写纯生sql,这意味着开发效率比方式2高,同时兼容方式2扩展性高的好处
缺点:执行效率连方式2都比不过
创建存储过程:
delimiter $$ create procedure p1( in m int, in n int, out res int ) begin select tname from teacher where tid > m and tid < n; set res=0; end $$ delimiter ; 对于存储过程,可以接收参数,其参数有三类: #in 仅用于传入参数用 #out 仅用于返回值用 #inout 既可以传入又可以当作返回值
如何用存储过程:
1、直接在mysql中调用
set @res=10 call p1(2,4,10); #查看结果 select @res;
2、在python程序中调用
import pymysql conn=pymysql.connect( host='127.0.0.1', port=3306, user='root', password='123', charset='utf8', database='db42' ) cursor=conn.cursor(pymysql.cursors.DictCursor) cursor.callproc('p1',(2,4,10)) #@_p1_0=2,@_p1_1=4,@_p1_2=10 print(cursor.fetchall()) cursor.execute('select @_p1_2;') #执行查看存储器 out 输出数据的值 print(cursor.fetchone()) #打印该输出值 cursor.close() conn.close()
事务与存储过程的使用:
delimiter // #将结束符号改为 '//' ,用以屏蔽sql代码块中的 ';' create PROCEDURE p5( OUT p_return_code tinyint # 设置一个 tinyint类型的 输出参数 p_return_code ) BEGIN DECLARE exit handler for sqlexception #声明代码段捕捉sqlexception异常 BEGIN -- ERROR set p_return_code = 1; # 1代表执行失败,遇到sqlexception异常 rollback; #回滚数据 END; DECLARE exit handler for sqlwarning #声明代码段捕捉sqlwarning异常 BEGIN -- WARNING set p_return_code = 2; # 2代表执行失败,遇到sqlwarning异常 rollback; #回滚数据 END; START TRANSACTION; #执行事务 update user set balance=900 where id =1; update user123 set balance=1010 where id = 2; update user set balance=1090 where id =3; COMMIT; #提交事务 -- SUCCESS set p_return_code = 0; #0代表执行成功 END // #存储过程结束 delimiter ; #将结束符号改回 ';'