mysql七:視圖、觸發器、事務、存儲過程、函數
視圖是一個虛擬表(非真實存在),其本質是【根據SQL語句獲取動態的數據集,並為其命名】,用戶使用時只需使用【名稱】即可獲取結果集,可以將該結果集當做表來使用。
使用視圖我們可以把查詢過程中的臨時表摘出來,用視圖去實現,這樣以後再想操作該臨時表的數據時就無需重寫復雜的sql了,直接去視圖中查找即可,但視圖有明顯地效率問題,並且視圖是存放在數據庫中的,如果我們程序中使用的sql過分依賴數據庫中的視圖,即強耦合,那就意味著擴展sql極為不便,因此並不推薦使用
1、創建視圖
語法:CREATE VIEW 視圖名稱 AS SQL語句
create view teacher_view as select tid from teacher where tname='李平老師';
!!!註意註意註意:
1)使用視圖以後就無需每次都重寫子查詢的sql,但是這麽效率並不高,還不如我們寫子查詢的效率高
2)而且有一個致命的問題:視圖是存放到數據庫裏的,如果我們程序中的sql過分依賴於數據庫中存放的視圖,那麽意味著,一旦sql需要修改且涉及到視圖的部分,則必須去數據庫中進行修改,而通常在公司中數據庫有專門的DBA負責,你要想完成修改,必須付出大量的溝通成本DBA可能才會幫你完成修改,極其地不方便。
2、使用視圖
修改視圖,原始表也跟著改
create view course_view as select * from course; #創建表course的視圖
select * from course_view;
update course_view set cname='xxx'; #更新視圖中的數據
insert into course_view values(5,'yyy',2); #往視圖中插入數據
select * from course; #發現原始表的記錄也跟著修改了
註:一般情況下不應該修改視圖中的記錄,而且在涉及多個表的情況下是根本無法修改視圖中的記錄
3、修改視圖
語法:ALTER VIEW 視圖名稱 AS SQL語句 (alter 變更)
alter view teacher_view as select * from course where cid>3;
4、刪除視圖
語法:DROP VIEW 視圖名稱
DROP VIEW teacher_view
二、觸發器
使用觸發器可以定制用戶對表進行【增、刪、改】操作時前後的行為。註意:沒有查詢!!!
1、創建觸發器
插入前
CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
BEGIN
...
END
插入後
CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW
BEGIN
...
END
刪除前
CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW
BEGIN
...
END
刪除後
CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW
BEGIN
...
END
更新前
CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW
BEGIN
...
END
更新後
CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW
BEGIN
...
END
舉個栗子:
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
特別的:NEW表示即將插入的數據行,OLD表示即將刪除的數據行。
2、使用觸發器
觸發器無法由用戶直接調用,而知由於對表的【增/刪/改】操作被動引發的。
3、刪除觸發器
drop trigger tri_after_insert_cmd;
三、事務
事務用於將某些操作的多個SQL作為原子性操作,一旦有某一個出現錯誤,即可回滾到原來的狀態,從而保證數據庫數據完整性。
create table user(
id int primary key auto_increment,
name char(32),
balance int
);
insert into user(name,balance)
values
('wsb',1000),
('egon',1000),
('ysb',1000);
#原子操作
start transaction;
update user set balance=900 where name='wsb'; #買支付100元
update user set balance=1010 where name='egon'; #中介拿走10元
update user set balance=1090 where name='ysb'; #賣家拿到90元
commit;
#出現異常,回滾到初始狀態
start transaction;
update user set balance=900 where name='wsb'; #買支付100元
update user set balance=1010 where name='egon'; #中介拿走10元
uppdate user set balance=1090 where name='ysb'; #賣家拿到90元,出現異常沒有拿到
rollback;
commit;
mysql> select * from user;
+----+------+---------+
| id | name | balance |
+----+------+---------+
| 1 | wsb | 1000 |
| 2 | egon | 1000 |
| 3 | ysb | 1000 |
+----+------+---------+
四、存儲過程
1、介紹
存儲過程包含了一系列可執行的sql語句,存儲過程存放於MySQL中,通過調用它的名字可以執行其內部的一堆sql
使用存儲過程的優點:
1)用於替代程序寫的SQL語句,實現程序與sql解耦
2)基於網絡傳輸,傳別名的數據量小,而直接傳sql數據量大
使用存儲過程的缺點:
1)程序員擴展功能不方便
補充:程序與數據庫結合使用的三種方式
方式一:
MySQL:存儲過程
程序:調用存儲過程
方式二:
MySQL:
程序:純SQL語句
方式三:
MySQL:
程序:類和對象,即ORM(本質還是純SQL語句)
2、創建簡單存儲過程(無參)
delimiter //
create procedure p1()
BEGIN
select * from blog;
INSERT into blog(name,sub_time) values("xxx",now());
END //
delimiter ;
在mysql中調用: call p1()
在python中基於pymysql調用
cursor.callproc('p1')
print(cursor.fetchall())
3、創建存儲過程(有參)
對於存儲過程,可以接收參數,其參數有三類:
in 僅用於傳入參數用
out 僅用於返回值用
inout 既可以傳入又可以當作返回值
4、執行存儲過程
-- 無參數:call proc_name()
-- 有參數,全in:call proc_name(1,2)
-- 有參數,有in,out,inout
set @t1=0;
set @t2=3;
call proc_name(1,2,@t1,@t2)
5、刪除存儲過程
drop procedure proc_name;
五 函數
MySQL中提供了許多內置函數
1、自定義函數
註意:函數中不要寫sql語句(否則會報錯),函數僅僅只是一個功能,是一個在sql中被應用的功能
若要想在begin...end...中寫sql,請用存儲過程
2、刪除函數
3、執行函數
六、流程控制
1、條件語句
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 ;
2、循環語句
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
mysql七:視圖、觸發器、事務、存儲過程、函數