MySQL學習筆記(11):儲存過程和函式
本文更新於2019-06-23,使用MySQL 5.7,作業系統為Deepin 15.4。
目錄
SQL語句
建立儲存過程或函式
建立儲存過程:
CREATE PROCEDURE name ({[IN|OUT|INOUT] param type}[, ...])
[characteristic]
body
建立函式:
CREATE FUNCTION name ({param type}[, ...]) RETURNS type [characteristic] body
type表示資料型別。
characteristic表示特徵值,特徵值目前只是提供資訊給伺服器,定義如下:
LANGUAGE SQL
|[NOT] DETERMINISTIC
|{CONTAINS SQL|NO SQL|READS SQL DATA|MODIFIES SQL DATA}
|SQL SECURITY {DEFINER|INVOKER}
|COMMENT 'string'
- LANGUAGE SQL:說明body是使用SQL編寫的。該值是預設的。
- [NOT] DETERMINISTIC:說明是確定的,即是否同樣的輸入產生同樣的輸出。預設為
NOT DETERMINISTIC
。 - CONTAINS SQL|NO SQL|READS SQL DATA|MODIFIES SQL DATA:目前並沒有根據此特徵值約束儲存過程實際對資料的使用。
CONTAINS SQL
NO SQL
表示不包含SQL語句;READS SQL DATA
表示包含讀語句不包含寫語句;MODIFIES SQL DATA
表示包含寫語句。預設為CONTAINS SQL
。 - SQL SECURITY {DEFINER|INVOKER}:表示使用建立者的許可權來執行,還是使用呼叫者的許可權來執行。預設為
DEFINER
。 - COMMENT 'string':註釋。
body由BEGIN
和END
包起,其中可以定義變數、條件、處理、遊標,以及使用流程控制語句跳轉邏輯。
儲存過程和函式的CREATE
語法不支援OR REPLACE
。
儲存過程和函式的區別:函式一定有返回值,儲存過程一定沒有返回值;函式的引數只能使用IN
IN
、OUT
、INOUT
型別。
MySQL的儲存過程和函式中允許包含DDL語句,允許執行提交或回滾,允許呼叫其他儲存過程或函式,但是是不允許執行LOAD DATA INFILE
語句。
通常在執行建立儲存過程或函式前,使用DELIMITER ;;
命令將語句的結束符從;
修改成其他符號(示例使用;;
)。在建立完畢後,通過DELIMITER ;
命令將結束符還原。這樣可避免儲存過程定義中的;
被錯誤解析為結束符。
修改儲存過程或函式
ALTER PROCEDURE|FUNCTION name
[characteristic]
characteristic特徵值如下:
{CONTAINS SQL|NO SQL|READS SQL DATA|MODIFIES SQL DATA}
|SQL SECURITY {DEFINER|INVOKER}
|COMMENT 'string'
刪除儲存過程或函式
DROP PROCEDURE|FUNCTION [IF EXISTS] name
一次只能刪除一個儲存過程或函式。
呼叫儲存過程或函式
CALL name(param[, ...])
如果是輸出引數,需傳入變數,如:@xxx
。
變數、條件、處理、遊標
變數、條件、處理、遊標都通過DECLARE
定義,但它們之間是有先後順序的:變數和條件必須在最前面宣告,然後才是遊標的宣告,最後才是處理的宣告。
變數
變數不區分大小寫,作用範圍只能在BEGIN ... END
塊中,可以用在巢狀的塊中。變數的定義必須寫在複合語句的開頭,並且在其他語句的前面。
DECLARE var[, ...] type [DEFAULT value]
變數直接賦值:
SET {var = value}[, ...]
變數通過查詢賦值,這要求查詢返回的結果只有一行:
SELECT colname[, ...] INTO var[, ...] FROM ...
FROM
後面的子句同普通的SELECT
查詢,在此省略。
條件
DECLARE condition_name CONDITION FOR
{SQLSTATE [VALUE] value}|mysql_error_code
條件枚的含義如下:
SQLSTATE [VALUE] value
:SQLSTATE程式碼,為一個字串。mysql_error_code
:mysql_error_code值,為一個整數。
處理
DECLARE CONTINUE|EXIT|UNDO HANDLER FOR
{SQLSTATE [VALUE] value|condition_name|SQLWARNING|NOT FOUND|SQLEXCEPTION|mysql_error_code}[, ...]
sp_statement
處理型別列舉值的含義:
CONTINUE
:繼續執行後面的語句。EXIT
:執行終止。UNDO
:前面已執行的語句撤銷,目前還不支援。
條件枚的含義如下:
SQLSTATE [VALUE] value
:SQLSTATE程式碼,為一個字串。condition_name
:DECLARE
定義的CONDITION
名。SQLWARNING
:所有以01開頭的SQLSTATE程式碼的速記。NOT FOUND
:所有以02開頭的SQLSTATE程式碼的速記。SQLEXCEPTION
:所有沒有被SQLWARNING
和NOT FOUND
捕獲的SQLSTATE程式碼的速記。mysql_error_code
:mysql_error_code值,為一個整數。
遊標
宣告遊標:
DECLARE cursor_name CURSOR FOR select_statement
開啟遊標:
OPEN cursor_name
讀取遊標:
FETCH cursor_name INTO var[, ...]
關閉遊標:
CLOSE cursor_name
流程控制
IF
IF condition1 THEN statement_list1
[ELSEIF condition2 THEN statement_list2]
[...]
[ELSE statement_list3]
END IF
CASE
CASE case_value
WHEN value1 THEN statement_list1
[...]
[ELSE statement_list2]
END CASE
或:
CASE
WHEN condition1 THEN statement_list1
[...]
[ELSE statement_list2]
END CASE
LEAVE
從標註的流程中退出,通常和BEGIN ... END
或迴圈一起使用。
LEAVE label
ITERATE
ITERATE
必須用在迴圈中,作用是跳過當前迴圈的剩下語句,進入下一輪迴圈。
ITERATE label
LOOP
通常需在statement_list中指定退出條件,否則為死迴圈。
[begin_label:] LOOP
statement_list
END LOOP [end_label]
WHILE
當滿足條件時執行迴圈。會在首次迴圈執行前判斷條件,故迴圈最少執行0次。
[begin_label:] WHILE condition DO
statement_list
END WHILE [end_label]
REPEAT
當滿足條件時退出迴圈。會在首次迴圈執行後判斷條件,故迴圈最少執行1次。
[begin_label:] REPEAT
statement_list
UNTIL condition
END REPEAT [end_label]
示例
儲存過程定義示例如下:
DELIMITER ;;
CREATE PROCEDURE sp_test(IN id INT, OUT sum INT)
BEGIN
DECLARE var_value, var_sum INT DEFAULT 0;
DECLARE flag INT DEFAULT 1;
DECLARE cur CURSOR FOR SELECT value FROM t WHERE tid = id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 0;
OPEN cur;
loop_cur: LOOP
FETCH cur INTO var_value;
IF flag = 0 THEN
LEAVE loop_cur;
END IF;
var_sum = var_sum + var_value;
END LOOP;
CLOSE cur;
END;;
DELIMITER ;