Linux 第68天 procedure,trigger,DCL
時間: 20181009
個人博客地址: www.winthcloud.top
目錄
存儲過程簡介
觸發器
DCL (Data Countrol Language)
存儲過程簡介
SQL語句需要先編譯然後執行,而存儲過程(Stored Procedure)是一組爲了完成特定功能的
SQL語句集,經編譯後存儲在數據庫中,用戶通過指定存儲過程的名字並給定參數(如果該存儲
過程帶有參數)來調用執行它。
存儲過程是可編程的函數,在數據庫中創建並保存,可以由SQL語句和控制結構組成。當想要在
不同的應用程序或平臺上執行相同的函數,或者封裝特定功能時,存儲過程是非常有用的。數據
庫中的存儲過程可以看做是對編程中面向對象方法的模擬,它允許控制數據的訪問方式。
存儲過程的優點:
(1).增強SQL語言的功能和靈活性:存儲過程可以用控制語句編寫,有很強的靈活性,可以
完成複雜的判斷和較複雜的運算。
(2).標準組件式編程:存儲過程被創建後,可以在程序中被多次調用,而不必重新編寫該存
儲過程的SQL語句。而且數據庫專業人員可以隨時對存儲過程進行修改,對應用程序源代碼毫
無影響。
(3).較快的執行速度:如果某一操作包含大量的Transaction-SQL代碼或分別被多次執行,
那麼存儲過程要比批處理的執行速度快很多。因爲存儲過程是預編譯的。在首次運行一個存
儲過程時查詢,優化器對其進行分析優化,並且給出最終被存儲在系統表中的執行計劃。
而批處理的Transaction-SQL語句在每次運行時都要進行編譯和優化,速度相對要慢一些。
(4).減少網絡流量:針對同一個數據庫對象的操作(如查詢、修改),如果這一操作所涉及
的Transaction-SQL語句被組織進存儲過程,那麼當在客戶計算機上調用該存儲過程時,
網絡中傳送的只是該調用語句,從而大大減少網絡流量並降低了網絡負載。
(5).作爲一種安全機制來充分利用:通過對執行某一存儲過程的權限進行限制,能夠實現
對相應的數據的訪問權限的限制,避免了非授權用戶對數據的訪問,保證了數據的安全。
存儲過程與自定義函數的區別
存儲過程實現的過程要複雜一些,而函數的針對性較強
存儲過程可以有多個返回值,而自定義函數只有一個返回值
存儲過程一般獨立的來執行,而函數往往是作爲其他SQL語句的一部分來使用
流程控制
存儲過程和函數中可以使用流程控制來控制語句的執行
流程控制:
IF:用來進行條件判斷。根據是否滿足條件,執行不同語句
CASE:用來進行條件判斷,可實現比IF語句更復雜的條件判斷
LOOP:重複執行特定的語句,實現一個簡單的循環
LEAVE:用於跳出循環控制
ITERATE:跳出本次循環,然後直接進入下一次循環
REPEAT:有條件控制的循環語句。當滿足特定條件時,就會跳出循環語句
WHILE:有條件控制的循環語句
存儲過程: 存儲過程保存在mysql.proc表中
創建存儲過程
CREATE PROCEDURE sp_name ([ proc_parameter [,proc_parameter ...]])
routime_body
其中:proc_parameter: [IN|OUT|INOUT] parameter_name type
其中IN表示輸入參數,OUT表示輸出參數,INOUT表示既可以輸入也可以輸出;
param_name表示參數名稱;type表示參數的類型
查看存儲過程列表
SHOW PROCEDURE STATUS;
查看存儲過程定義
SHOW CREATE PROCEDURE sp_name;
調用存儲過程
CALL sp_name ([ proc_parameter [,proc_parameter ...]])
CALL sp_name
說明:當無參時,可以省略"()",當有參數時,不可省略"()"
存儲過程修改
ALTER語句修改存儲過程只能修改存儲過程的註釋等無關緊要的東西,不能修改存儲過程體
所以要修改存儲過程,方法就是刪除重建
刪除存儲過程
DROP PROCEDURE [IF EXISTS] sp_name;
存儲過程示
創建無參存儲過程
DELIMITER //
CREATE PROCEDURE showTime()
BEGIN
SELECT now();
END //
DELIMITER ;
CALL showTime;
創建含參存儲過程:只有一個IN參數
DELIMITER //
CREATE PROCEDURE selectById(IN uid SMALLINT UNSIGNED)
BEGIN
SELECT * FROM students WHERE stuid = uid;
END //
DELIMITER ;
CALL selectById(2);
只有一個IN參數(帶變量)
DELIMITER //
CREATE PROCEDURE dorepeat(n INT)
BEGIN
SET @i=0;
SET @sum=0;
REPEAT SET @sum = @sum+@i; SET @i=@i+1;
UNTIL @i > n END REPEAT;
END //
DELIMITER ;
CALL dorepeat(100);
SELECT @sum;
創建含參存儲過程:包含IN參數和OUT參數
DELIMITER //
CREATE PROCEDURE deleteById(IN uid SMALLINT UNSIGNED,
OUT num SMALLINT UNSIGNED)
BEGIN
DELETE FROM students WHERE stuid = uid;
SELECT row_count() INTO num;
END //
DELIMITER ;
CALL deleteById(2,@Line);
SELECT @Line;
說明:創建存儲過程deleteById,包含一個IN參數和一個OUT參數.調用時,傳入刪除的ID和
保存被修改的行數值的用戶變量@Line,select @Line;輸出被影響行數
觸發器
觸發器的執行不是由程序調用,也不是由手工啓動,而是由事件來觸發、激活從而實現執行
觸發器是與表有關的數據庫對象,在滿足定義條件時觸發,並執行觸發器中定義的語句集合。
觸發器的特性:
有begin end體,begin end;之間的語句可以寫的簡單或者複雜
觸發條件:I、D、U
觸發機制:在增刪改前或者後
觸發頻率:針對每一行執行
觸發器定義附着在表上。
也就是由事件來觸發某個操作,事件包括INSERT語句,UPDATE語句和DELETE語句;可以協助
應用在數據庫端確保數據的完整性。
注意:cannot associate a trigger with a TEMPORARY table or a view.
創建觸發器
CREATE
[DEFINER = { user | CURRENT_USER }]
TRIGGER trigger_name
trigger_time trigger_event
ON tbl_name FOR EACH ROW
trigger_body
說明:
trigger_name:觸發器的名稱
trigger_time:{ BEFORE | AFTER },表示在事件之前或之後觸發
trigger_event::{ INSERT |UPDATE | DELETE },觸發的具體事件
tbl_name:該觸發器作用在表名
查看觸發器
SHOW TRIGGERS
查詢系統表information_schema.triggers的方式指定查詢條件,查看指定的觸發器信息。
mysql> USE information_schema;
mysql> SELECT * FROM triggers WHERE
trigger_name='trigger_student_count_insert';
刪除觸發器
DROP TRIGGER trigger_name;
觸發器示例
CREATE TABLE student_info(
stu_id INT(11) NOT NULL AUTO_INCREMENT,
stu_name VARCHAR(255) DEFAULT NULL,
PRIMARY KEY(stu_id)
);
CREATE TABLE student_count(
student_count INT(11) DEFAULT 0
);
INSERT INTO student_count VALUES(0);
示例:創建觸發器,在向學生表INSERT數據時,學生數增加,DELETE學生時,學生數減少
CREATE TRIGGER trigger_student_count_insert
AFTER INSERT
ON student_info FOR EACH ROW
UPDATE student_count SET student_count=student_count+1;
CREATE TRIGGER trigger_student_delete
AFTER DELETE
ON student_info FOR EACH ROW
UPDATE student_count SET student_count=student_count-1;
DCL (Data Countrol Language)
GRANT REVOKE
用戶和權限管理
元數據數據庫:mysql
系統授權表:
db, host, user
columns_priv, tables_priv, procs_priv, proxies_priv
創建用戶:CREATE USER
CREATE USER 'USERNAME'@'HOST' [IDENTIFIED BY 'password'];
默認權限:USAGE
用戶重命名:RENAME USER
RENAME USER old_user_name TO new_user_name
刪除用戶:
DROP USER 'USERNAME'@'HOST‘
示例:刪除默認的空用戶
DROP USER ''@'localhost';
修改密碼:
mysql>SET PASSWORD FOR 'user'@'host' = PASSWORD('password');
mysql>UPDATE mysql.user SET password=PASSWORD('password') WHERE clause;
此方法需要執行下面指令才能生效:
mysql> FLUSH PRIVILEGES;
mysqladmin -u root -poldpass password 'newpass'
忘記管理員密碼的解決辦法:
啓動mysqld進程時,爲其使用如下選項:
--skip-grant-tables 表示跳過權限認證
--skip-networking 表示不啓用網絡接口
使用UPDATE命令修改管理員密碼
關閉mysqld進程,移除上述兩個選項,重啓mysqld
權限類別:
管理類:
CREATE TEMPORARY TABLES
CREATE USER
FILE
SUPER
SHOW DATABASES
RELOAD
SHUTDOWN
REPLICATION SLAVE
REPLICATION CLIENT
LOCK TABLES
PROCES
程序類: FUNCTION、PROCEDURE、TRIGGER
CREATE
ALTER
DROP
EXCUTE
庫和表級別:DATABASE、TABLE
ALTER
CREATE
CREATE VIEW
DROP
INDEX
SHOW VIEW
GRANT OPTION:能將自己獲得的權限轉贈給其他用戶
數據操作:
SELECT
INSERT
DELETE
UPDATE
字段級別:
SELECT(col1,col2,...)
UPDATE(col1,col2,...)
INSERT(col1,col2,...)
所有權限:ALL PRIVILEGES 或 ALL
授權
參考:https://dev.mysql.com/doc/refman/5.7/en/grant.html
GRANT priv_type [(column_list)],...
ON [object_type] priv_level
TO 'user'@'host' [IDENTIFIED BY 'password'] [WITH GRANT OPTION];
priv_type: ALL [PRIVILEGES]
object_type:TABLE | FUNCTION | PROCEDURE
priv_level: *(所有庫) | *.* | db_name.* | db_name.tbl_name |
tbl_name(當前庫的表) | db_name.routine_name(指定庫的函數,存儲過程,觸發器)
with_option: GRANT OPTION
| MAX_QUERIES_PER_HOUR count
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONS count
回收授權
REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ...
ON [object_type] priv_level FROM user [, user] ...
示例:
REVOKE DELETE ON testdb.* FROM 'testuser'@'%‘
查看指定用戶獲得的授權:
Help SHOW GRANTS
SHOW GRANTS FOR 'user'@'host';
SHOW GRANTS FOR CURRENT_USER[()];
注意:MariaDB服務進程啓動時會讀取mysql庫中所有授權表至內存
(1) GRANT或REVOKE等執行權限操作會保存於系統表中,MariaDB的服務進程通常會自
動重讀授權表,使之生效
(2) 對於不能夠或不能及時重讀授權表的命令,可手動讓MariaDB的服務進程重讀授權表
mysql> FLUSH PRIVILEGES;