6、儲存過程與儲存函式
阿新 • • 發佈:2022-03-26
儲存過程(Stored Procedure)
多條 SQL 語句處理多個表,儲存過程是一組為了完成特定功能的 SQL 語句集合。
一組經過預先編譯的SQL語句的封裝,呼叫者無需考慮邏輯功能的具體實現過程,它可以被 Java 和 C# 等呼叫。
使用儲存過程的目的是將常用或複雜的工作預先用 SQL 語句寫好並用一個指定名稱儲存起來,這個過程經編譯和優化後儲存在資料庫伺服器中,因此稱為儲存過程。
優點
- 簡化操作,提高了sql語句的重用性
- 減少操作過程中的失誤,提高效率
- 減少編譯次數,減少和資料庫連線次數
- 減少網路傳輸量(客戶端不需要把所有的 SQL 語句通過網路發給伺服器)
- 減少了 SQL 語句暴露在網上的風險,也提高了資料查詢的安全性
建立使用
- 可以使用 CREATE PROCEDURE 語句建立儲存過程。
-
語法格式如下:
DELIMITER 新的結束標記 CREATE PROCEDURE 儲存過程名(IN|OUT|INOUT 引數名 引數型別,...)[characteristics ...] BEGIN 儲存過程體 END 新的結束標記 DELIMITER ;
- 沒有引數(無引數無返回);僅僅帶 IN 型別(有引數無返回)
- 僅僅帶 OUT 型別(無引數有返回);既帶 IN 又帶 OUT(有引數有返回)
-
帶 INOUT(有引數有返回)。IN、OUT、INOUT 都可以在一個儲存過程中帶多個。
-
儲存過程體中間包含了多條 SQL 語句,每個語句都以(;)號為結束符。DECLARE:用來宣告變數,使用的位置在於 BEGIN…END 語句中間,而且需要在其他語句使用之前進行變數的宣告。
- 如果僅僅一條SQL 語句,則可以省略 BEGIN 和 END
- SET:賦值語句,用於對變數進行賦值。
- SELECT… INTO:把從資料表中查詢的結果存放到變數中,也就是為變數賦值。
-
需要設定新的結束標記:DELIMITER 新的結束標記
- 因為MySQL預設的語句結束符號為分號';'。為了避免與儲存過程中SQL語句結束符相沖突,需要使用DELIMITER改變儲存過程的結束符。
- 儲存過程定義完畢之後再使用“DELIMITER ;”恢復預設結束符。
- 當使用DELIMITER命令時,應該避免使用反斜槓(‘\’)字元,因為反斜線是MySQL的轉義字元。
示例1:無引數的儲存過程
-- 建立測試表
CREATE TABLE test (tid int);
-- 刪除儲存過程
DROP PROCEDURE p1;
DROP PROCEDURE p2;
DROP PROCEDURE p3;
-
批量插入
-- 示例1:無引數的儲存過程. -- 建立儲存過程 CREATE PROCEDURE p1 () BEGIN #宣告區域性變數 DECLARE i INT DEFAULT 1; #迴圈 WHILE i<=10 DO #迴圈體 往test表批量插入資料 INSERT INTO test (tid) VALUES (i); #改變迴圈條件 SET i=i+1; END WHILE; -- 檢視test表資料 SELECT*from test; END; -- 呼叫儲存過程 CALL p1 ();
-
Loop
-- 建立儲存過程 CREATE PROCEDURE p2() BEGIN #宣告區域性變數 DECLARE i INT DEFAULT 1; #迴圈 lp : LOOP #迴圈體 往test表批量插入資料 INSERT INTO test (tid) VALUES (i); #改變迴圈條件 SET i=i+1; #條件語句判斷迴圈結束條件 IF i>10 THEN LEAVE lp; #退出迴圈 END IF; END LOOP; -- 檢視test表資料 SELECT * from test; END; -- 呼叫儲存過程 CALL p2 ();
-
Repeat
-- 建立儲存過程 CREATE PROCEDURE p3() BEGIN #宣告區域性變數 DECLARE i INT DEFAULT 1; #迴圈 REPEAT #迴圈體 往test表批量插入資料 INSERT INTO test (tid) VALUES ( i); #改變迴圈條件 SET i=i+1; #退出迴圈 UNTIL i>10 END REPEAT; -- 檢視test表資料 SELECT * from test; END; -- 呼叫儲存過程 CALL p3 ();
示例2:有in和out引數的儲存過程
-
練習:根據賬戶編號,返回賬戶餘額,使用者等級。
- -- 餘額>=2000,顯示使用者等級'磚石會員-- 餘額>=1500,顯示使用者等級'鉑金會員'
-
-- 餘額>=1000,顯示使用者等級'黃金會員-- 餘額>=500,顯示使用者等級'大眾會員'
-- 建立儲存過程 DROP PROCEDURE p4; create procedure p4( IN in_account_id varchar(36), OUT out_balance decimal, -- 十進位制 OUT out_level varchar(20) ) BEGIN SELECT balance, CASE WHEN balance>=2000 THEN '鑽石會員' WHEN balance>=1500 THEN '鉑金會員' WHEN balance>=1000 THEN '黃金會員' WHEN balance>=500 THEN '大眾會員' ELSE '普通會員' END AS balance_level INTO out_balance,out_level from account where account_id=in_account_id; END; SET @in_account_id='aec8301d-ab3b-11ec-b6ed-0a0027000018'; -- account 表中有的資料 CALL p4(@in_account_id,@out_balance,@out_level); -- 呼叫 SELECT @out_balance,@out_level; -- select輸出出參
呼叫儲存過程
-
儲存過程有多種呼叫方法。儲存過程必須使用CALL語句呼叫,並且儲存過程和資料庫相關,如果要執行其他資料庫中的儲存過程,需要指定資料庫名稱。
CALL 儲存過程名(實參列表) -- 1. 呼叫in模式的引數: CALL 儲存過程名('值'); -- 2. 呼叫out模式的引數: SET @name; CALL 儲存過程名(@name); SELECT @name; -- 3. 呼叫inout模式的引數: SET @name=值; CALL 儲存過程名(@name); SELECT @name;
刪除
DROP PROCEDURE [IF EXISTS] 儲存過程的名;
儲存函式
建立
DELIMITER 新的結束標記
CREATE FUNCTION 函式名(引數名 引數型別,...)
RETURNS 返回值型別
[characteristics ...]
BEGIN
函式體 RETURN 語句
END 新的結束標記
DELIMITER ;
- 引數列表:指定引數為IN、OUT或INOUT只對PROCEDURE是合法的,FUNCTION中總是預設為IN引數。
-
RETURNS type 語句表示函式返回資料的型別;
- RETURNS子句只能對FUNCTION做指定,對函式而言這是
強制
的。 - 它用來指定函式的返回型別,而且函式體必須包含一個
RETURN value
語句。
- RETURNS子句只能對FUNCTION做指定,對函式而言這是
- characteristic 建立函式時指定的對函式的約束。
- 函式體也可以用BEGIN…END來表示SQL程式碼的開始和結束。如果函式體只有一條語句,也可以省略BEGIN…END。
呼叫儲存函式
SELECT 函式名(實參列表)
刪除
DROP FUNCTION [IF EXISTS] 儲存函式的名;
對比儲存函式和儲存過程
關鍵字 | 呼叫語法 | 返回值 | 應用場景 | |
---|---|---|---|---|
儲存過程 | PROCEDURE | CALL 儲存過程() | 理解為有0個或多個 | 一般用於更新 |
儲存函式 | FUNCTION | SELECT 函式() | 只能是一個 | 一般用於查詢結果為一個值並返回時 |
此外,儲存函式可以放在查詢語句中使用,儲存過程不行。反之,儲存過程的功能更加強大,包括能夠執行對錶的操作(比如建立表,刪除表等)和事務操作,這些功能是儲存函式不具備的。