mysql內置功能: 1.視圖 2.觸發器 3.存儲過程 4.事務 5.函數
6.函數流程控制
一、視圖
介紹:
視圖是一個虛擬表(非真實存在),其本質是【根據SQL語句獲取動態的數據集,並為其命名】, 用戶使用時只需使用【名稱】即可獲取結果集,可以將該結果集當做表來使用。 使用視圖我們可以把查詢過程中的臨時表摘出來,用視圖去實現, 這樣以后再想操作該臨時表的數據時就無需重寫復雜的sql了,直接去視圖中查找即可, 但視圖有明顯地效率問題,並且視圖是存放在數據庫中的, 如果我們程序中使用的sql過分依賴數據庫中的視圖,即強耦合,那就意味着擴展sql極為不便, 因此並不推薦使用; 把sql語句查詢出來得虛擬表保存下來; 視圖:硬盤只存結構,不存數據,因為數據本身來源於其他表 減少代碼冗余,但是不建議使用,數據庫擴展,就影響視圖,就得修改視圖。 視圖得目的:取代復雜得sql語句,針對單表做視圖,沒有意義; 視圖是用來查得,多張表,視圖數據不應該被改, 視圖是方便來查得,不是用來改得!
#兩張有關系的表 mysql> select * from course; +-----+--------+------------+ | cid | cname | teacher_id | +-----+--------+------------+ | 1 | 生物 | 1 | | 2 | 物理 | 2 | | 3 | 體育 | 3 | | 4 | 美術 | 2 | +-----+--------+------------+ rows in set (0.00 sec) mysql> select * from teacher; +-----+-----------------+ | tid | tname | +-----+-----------------+ | 1 | 張磊老師 | | 2 | 李平老師 | | 3 | 劉海燕老師 | | 4 | 朱雲海老師 | | 5 | 李傑老師 | +-----+-----------------+ rows in set (0.00 sec) #查詢李平老師教授的課程名 mysql> select cname from course where teacher_id = (select tid from teacher where tname='李平老師'); +--------+ | cname | +--------+ | 物理 | | 美術 | +--------+ rows in set (0.00 sec) #子查詢出臨時表,作為teacher_id等判斷依據 select tid from teacher where tname='李平老師' 臨時表應用舉例
1、創建視圖
#語法:CREATE VIEW 視圖名稱 AS SQL語句 create view teacher_view as select tid from teacher where tname='李平老師'; #於是查詢李平老師教授的課程名的sql可以改寫為 mysql> select cname from course where teacher_id = (select tid from teacher_view); +--------+ | cname | +--------+ | 物理 | | 美術 | +--------+ rows in set (0.00 sec) #!!!注意注意注意: #1. 使用視圖以后就無需每次都重寫子查詢的sql,但是這么效率並不高,還不如我們寫子查詢的效率高 #2. 而且有一個致命的問題:視圖是存放到數據庫里的,如果我們程序中的sql過分依賴於數據庫中存放的視圖, 那么意味着,一旦sql需要修改且涉及到視圖的部分,則必須去數據庫中進行修改,而通常在公司中數據庫有專門的DBA負責, 你要想完成修改,必須付出大量的溝通成本DBA可能才會幫你完成修改,極其地不方便
2、使用視圖
#修改視圖,原始表也跟着改 mysql> select * from course; +-----+--------+------------+ | cid | cname | teacher_id | +-----+--------+------------+ | 1 | 生物 | 1 | | 2 | 物理 | 2 | | 3 | 體育 | 3 | | 4 | 美術 | 2 | +-----+--------+------------+ rows in set (0.00 sec) mysql> create view course_view as select * from course; #創建表course的視圖 Query OK, 0 rows affected (0.52 sec) mysql> select * from course_view; +-----+--------+------------+ | cid | cname | teacher_id | +-----+--------+------------+ | 1 | 生物 | 1 | | 2 | 物理 | 2 | | 3 | 體育 | 3 | | 4 | 美術 | 2 | +-----+--------+------------+ rows in set (0.00 sec) mysql> update course_view set cname='xxx'; #更新視圖中的數據 Query OK, 4 rows affected (0.04 sec) Rows matched: 4 Changed: 4 Warnings: 0 mysql> insert into course_view values(5,'yyy',2); #往視圖中插入數據 Query OK, 1 row affected (0.03 sec) mysql> select * from course; #發現原始表的記錄也跟着修改了 +-----+-------+------------+ | cid | cname | teacher_id | +-----+-------+------------+ | 1 | xxx | 1 | | 2 | xxx | 2 | | 3 | xxx | 3 | | 4 | xxx | 2 | | 5 | yyy | 2 | +-----+-------+------------+ rows in set (0.00 sec)
3、修改視圖
語法:ALTER VIEW 視圖名稱 AS SQL語句 mysql> alter view teacher_view as select * from course where cid>3; Query OK, 0 rows affected (0.04 sec) mysql> select * from teacher_view; +-----+-------+------------+ | cid | cname | teacher_id | +-----+-------+------------+ | 4 | xxx | 2 | | 5 | yyy | 2 | +-----+-------+------------+ rows in set (0.00 sec)
4、刪除視圖
語法:DROP VIEW 視圖名稱
DROP VIEW teacher_view
二、 觸發器
使用觸發器可以定制用戶對表進行【增、刪、改】操作時前后的行為,注意:沒有查詢
增 before insert ; after insert
1、創建觸發器
trigger 英 /'trɪgə/ 美 /'trɪɡɚ/ vt 觸發、引發
create trigger tri_before_insert_tb1 before insert on tb1 for each row # row 行
# 插入前 觸發 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
delimiter英 /dɪ'lɪmɪtə/ ,美 /dɪ'lɪmɪtɚ/ 定界符,分隔符
默認情況下,mysql解釋器一遇到分號(;),它就要自動執行。 不會等到用戶把這些語句全部輸入完之后,再執行整段語句。 而自定義函數和存儲過程的SQL語句有好多行,且語句中包含有分號, 為了保證整段語句的整體執行,就要使用delimiter,更改mysql的默認結束符。
先將分隔符設置為 //,
直到遇到下一個 //,才整體執行語句。
執行完后,最后一行, delimiter ; 將mysql的分隔符重新設置為分號;
如果不修改的話,本次會話中的所有分隔符都以// 為准。
先准備表,在創建觸發器,
#准備表 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 #等值判斷只有一個等號 NEW是新增加進來的數據 修改old是老記錄 INSERT INTO errlog(err_cmd, err_time) VALUES(NEW.cmd, NEW.sub_time) ; #必須加分號 END IF ; #必須加分號 END// delimiter ; #往表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'); #查詢錯誤日志,發現有兩條 mysql> select * from errlog; +----+-----------------+---------------------+ | id | err_cmd | err_time | +----+-----------------+---------------------+ | 1 | cat /etc/passwd | 2017-09-14 22:18:48 | | 2 | useradd xxx | 2017-09-14 22:18:48 | +----+-----------------+---------------------+ rows in set (0.00 sec) 插入后觸發觸發器
特別的:NEW表示即將插入的數據行,OLD表示即將刪除的數據行。
應用開發程序員 和 數據庫程序員是兩個部分,所以實際上部分溝通問題,所以實際開發時程序員自己設計觸發器,
二 使用觸發器
觸發器無法由用戶直接調用,而知由於對表的【增/刪/改】操作被動引發的。
三 刪除觸發器
drop trigger tri_after_insert_cmd;