存儲過程是一組實現特定功能的SQL語句集合,存儲過程一經編譯便存儲在了服務器上,能夠經過調用存儲過程的名字以及傳入相應的參數來使用存儲過程。要高層次的掌握存儲過程,不能以爲依葫蘆畫瓢,以爲造出來的存儲過程可以跑出結果就OK。必定要站在必定的高度,看清它的全貌:mysql
存儲過程在定義的時候,有一些關鍵字的含義以及語句仍是須要搞明白的好,諸如分隔符的臨時重定義,調用存儲過程的權限控制等。
在sqllog等這些工具中新建一個存儲過程就會出現一下屬性和定義:sql
DELIMITER $$ CREATE /*[DEFINER = { user | CURRENT_USER }]*/ PROCEDURE `my_db`.`heat_test1`() /*LANGUAGE SQL | [NOT] DETERMINISTIC | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER } | COMMENT 'string'*/ BEGIN END$$ DELIMITER ;
在mysql的客戶端中向服務器傳送存儲過程的時候,若是不從新定義分號,mysql服務器接收到第一個分號的時候,會覺得這條語句傳送完畢,所以分割了整個存儲過程;爲了可以完整的將存儲過程傳送到服務器,務必須要暫時定義mysql的分隔符即分號;
使用 delimiter 關鍵字能夠從新定義分隔符,好比 mysql> delimiter //;固然能夠想使用你喜歡的字符代替「//」,可是不要使用「」,由於該符號在mysql中是轉移字符。
當整個存儲過程傳送完畢後,必定要記得將分隔符從新定義爲分號。數據庫
對於每個存儲過程,能夠有一個「DEFINER」的屬性,這個屬性是一個mysql中的帳戶名,好比root等。這個屬性幫助在調用存儲過程的時候,根據上下文的環境肯定其權限。若是這個屬性沒有明確給出,那麼mysql默認爲建立該存儲過程的用戶爲這個屬性的值。
此外,存儲過程當中還有一個SQL SECURITY { DEFINER | INVOKER }來決定使用存儲過程的定義者或者是調用者的上下文環境。若是是DEFINER,那麼這個存儲過程在調用的時候就會擁有建立者指定帳戶的權限,若是是INVOKER,那麼執行這個存儲過程的時候就會擁有調用者的權限。編程
CREATE DEFINER = 'admin'@'localhost' PROCEDURE p1() SQL SECURITY DEFINER BEGIN UPDATE t1 SET counter = counter + 1; END;
上面的存儲過程的SQL SECURITY定義的是DEFINER,所以對於任何有權限調用p1的用戶均可以用call來調用該存儲過程,可是在存儲過程執行的過程當中,上下文環境將切換到'admin'@'localhost'用戶下,也就是說調用者的權限對此存儲過程無效(調用者能夠沒有對t1表updata權限,只要'admin'@'localhost'有便可),在這個存儲過程執行的時候,所擁有的權限是'admin'@'localhost'所擁有的。安全
CREATE DEFINER = 'admin'@'localhost' PROCEDURE p2() SQL SECURITY INVOKER BEGIN UPDATE t1 SET counter = counter + 1; END;
當存儲過程p2的SQL SECURITY定義爲INVOKER的時候,這個時候存儲執行的上下文環境將在調用者上下文環境中執行,也就是說,這個時候調用者的權限必需要有對t1表的訪問和修改權限。服務器
經過這樣的權限設置,能夠實現更細粒度以及更自由的權限設置。同時,基於安全的問題也要時時考慮到。網絡
參考文獻
[1] 高性能mysql
[2] mysql官方網站函數