1. 程式人生 > >mysql七:視圖、觸發器、事務、存儲過程、函數

mysql七:視圖、觸發器、事務、存儲過程、函數

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七:視圖、觸發器、事務、存儲過程、函數