視圖是一個虛擬表(非真實存在),其本質是【根據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