视图是一个虚拟表(非真实存在),其本质是【根据SQL语句获取动态的数据集,并为其命名】,用户使用时只需使用【名称】便可获取结果集,能够将该结果集当作表来使用;mysql
使用视图咱们能够把查询过程当中的临时表摘出来,用视图去实现,这样之后再想操做该临时表的数据时就无需重写复杂的sql了,直接去视图中查找便可,但视图有明显地效率问题,而且视图是存放在数据库中的,若是咱们程序中使用的sql过度依赖数据库中的视图,即强耦合,那就意味着扩展sql极为不便,所以并不推荐使用。程序员
ps: 视图在库里只有表结构文件没有表数据sql
咱们不该该修改视图中的记录,并且在涉及多个表的状况下是根本没法修改视图中的记录的数据库
# =============================建立视图 select * from emp inner join dep on emp.dep_id = dep.id; create view emp2dep as select emp.*,dep.name as dep_name from emp inner join dep on emp.dep_id = dep.id; mysql> update emp2dep set name="EGON" where id=1; Query OK, 1 row affected (0.05 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from emp2dep; +----+-----------+--------+------+--------+--------------+ | id | name | sex | age | dep_id | dep_name | +----+-----------+--------+------+--------+--------------+ | 1 | EGON | male | 18 | 200 | 技术 | | 2 | alex | female | 48 | 201 | 人力资源 | | 3 | wupeiqi | male | 38 | 201 | 人力资源 | | 4 | yuanhao | female | 28 | 202 | 销售 | | 5 | liwenzhou | male | 18 | 200 | 技术 | +----+-----------+--------+------+--------+--------------+ 5 rows in set (0.00 sec) mysql> mysql> mysql> select * from emp; +----+------------+--------+------+--------+ | id | name | sex | age | dep_id | +----+------------+--------+------+--------+ | 1 | EGON | male | 18 | 200 | | 2 | alex | female | 48 | 201 | | 3 | wupeiqi | male | 38 | 201 | | 4 | yuanhao | female | 28 | 202 | | 5 | liwenzhou | male | 18 | 200 | | 6 | jingliyang | female | 18 | 204 | | 7 | lili | female | 48 | NULL | +----+------------+--------+------+--------+ 7 rows in set (0.00 sec) mysql> # =============================修改视图 alter view emp2dep as 查询语句; # =============================删除视图 drop view emp2dep;
2、触发器
使用触发器能够定制用户对表进行【增、删、改】操做时先后的行为,注意:没有查询网络
特别的:NEW表示即将插入的数据行,OLD表示即将删除的数据行ide
触发器没法由用户直接调用,而知因为对表的【增/删/改】操做被动引起的。oop
# 增=》insert create trigger tri_before_insert_t1 before insert on t1 for each row begin sql语句; end create trigger tri_after_insert_t1 after insert on t1 for each row begin sql语句; end # 删除=》delete create trigger tri_before_delete_t1 before delete on t1 for each row begin sql语句; end create trigger tri_after_delete_t1 after delete on t1 for each row begin sql语句; end # 修改=》update # 例如 insert into tt1 values(1,"egon",'male'); delimiter // create trigger tri_before_insert_tt1 before insert on tt1 for each row begin insert into tt2 values(NEW.name); end // delimiter ; insert into tt1 values(2,"tom",'female'); # 练习 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 ; 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 ;
3、存储过程
存储过程包含了一系列可执行的sql语句,存储过程存放于MySQL中,经过调用它的名字能够执行其内部的一堆sqlfetch
使用存储过程的 优势: 1. 用于替代程序写的SQL语句,实现程序与sql解耦 2. 基于网络传输,传别名的数据量小,而直接传sql数据量大 缺点: 1. 程序员扩展功能不方便
程序与数据库结合使用的三种方式spa
#方式一:
MySQL:存储过程
程序:调用存储过程对象
#方式二:
MySQL:
程序:纯SQL语句
#方式三:
MySQL:
程序:类和对象,即ORM(本质仍是纯SQL语句)
对于存储过程,能够接收参数,其参数有三类: in 仅用于传入参数用 out 仅用于返回值用 inout 既能够传入又能够看成返回值
# 建立无参存储过程 delimiter $$ create procedure p1() begin select * from emp; end $$ delimiter ; call p1(); # 建立有参存储过程 delimiter $$ create procedure p2( in n int, out res int ) begin select * from emp where id > n; set res=1; end $$ delimiter ; ==========================>在mysql里调用存储过程 mysql> set @x=1111; Query OK, 0 rows affected (0.00 sec) mysql> call p2(3,x); ERROR 1414 (42000): OUT or INOUT argument 2 for routine db4.p2 is not a variable or NEW pseudo-variable in BEFORE trigger mysql> call p2(3,@x); +----+------------+--------+------+--------+ | id | name | sex | age | dep_id | +----+------------+--------+------+--------+ | 4 | yuanhao | female | 28 | 202 | | 5 | liwenzhou | male | 18 | 200 | | 6 | jingliyang | female | 18 | 204 | | 7 | lili | female | 48 | NULL | +----+------------+--------+------+--------+ 4 rows in set (0.00 sec) Query OK, 0 rows affected (0.01 sec) mysql> select @x; +------+ | @x | +------+ | 1 | +------+ 1 row in set (0.00 sec)
==========================>在pymysql里调用存储过程
import pymysql # pip3 install pymysql conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", password="123", db="db4", charset="utf8mb4") cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.callproc('p2',(3,0)) # @_p2_0=3,@_p2_1=0 ''' set @_p2_0=3 set @_p2_1=0 call p2(@_p2_0,@_p2_1); ''' print(cursor.fetchall()) cursor.execute("select @_p2_1;") print(cursor.fetchall()) cursor.execute("select @_p2_0;") print(cursor.fetchall()) cursor.close() conn.close()
==========================>删除存储过程
drop procedure proc_name;
条件语句
#if条件语句 delimiter // CREATE PROCEDURE proc_if () BEGIN declare i int default 0; if i = 1 THEN SELECT 1; ELSEIF i = 2 THEN SELECT 2; ELSE SELECT 7; END IF; END // delimiter ;
循环语句
#while循环语句 delimiter // CREATE PROCEDURE proc_while () BEGIN DECLARE num INT ; SET num = 0 ; WHILE num < 10 DO SELECT num ; SET num = num + 1 ; END WHILE ; END // delimiter ;
#repeat 循环 delimiter // CREATE PROCEDURE proc_repeat () BEGIN DECLARE i INT ; SET i = 0 ; repeat select i; set i = i + 1; until i >= 5 end repeat; END // delimiter ;
#loop循环 BEGIN declare i int default 0; loop_label: loop set i=i+1; if i<8 then iterate loop_label; end if; if i>=10 then leave loop_label; end if; select i; end loop loop_label; END