1. 程式人生 > >MySQL基礎系列之 儲存過程和函式

MySQL基礎系列之 儲存過程和函式

摘要:儲存過程和函式是事先經過編譯並存儲在資料庫中的一段SQL語句的集合
儲存過程無返回值,函式有返回值
儲存過程的引數可以使用IN、OUT、INOUT,函式只能使用IN
建立儲存過程 CREATE PROCEDURE
建立函式使用 CREATE FUNCTION
使用CALL語句來呼叫儲存過程

1、儲存過程
(1.1)建立語句
CREATE PROCEDURE sp_name([ proc_parameter ]) [characteristics] routine_body
(1.2)引數說明
sp_name:儲存過程名稱
proc_parameter: IN | OUT | INOUT param_name type
IN:輸入引數
OUT:輸出引數
INOUT:既可以輸入也可以輸出
param_name 引數名稱
type 引數型別


characteristics:儲存過程的特性
LANGUAGE SQL
說明routine_body部分是由sql語句組成當前系統支援的語言
[NOT] DETERMINISTIC
指明儲存過程執行的結果是否正確即相同的輸入得到的結果是否相同
DETERMINISTIC
相同的輸入得到的結果相同
NOT DETERMINISTIC
相同的輸入得到的結果不相同
CONTAINS SQL | NO SQL | READS SQL DATA | MODEIFIES SQL DATA
指明子程式使用SQL語句的限制
CONTAINS SQL
包含sql語句但不包含讀寫資料的語句
NO SQL
子程式不包含sql語句
READS SQL DATA
包含讀資料語句
MODIFIES SQL DATA
包含寫資料語句
SQL SECURITY{DEFINER}{INVOKER}
指明誰有許可權來執行
DEFINER
表示只有定義者才能執行(預設)
INVOKER
表示擁有許可權者可以執行
COMMENT ‘String’
註釋資訊 可以用來描述儲存過程或函式

routine_body
是sql程式碼內容 可以用BEGIN…END來表示sql語句的開始和結束

DELIMITER //
作用:將mysql結束符設為// 可以避免與 儲存過程中的sql語句結束符衝突
儲存過程定義完之後使用 DELIMITER ; 恢復預設結束符

(1.3)建立儲存過程例項

DELIMITER//
CREATE PROCEDURE avgFruitPrice2(OUT avgprice DOUBLE)
BEGIN
    SELECT AVG(price) INTO avgprice
    FROM tb_proceduretest;
END//
DELIMITER;

(1.4)呼叫儲存過程
CALL avgFruitPrice2(@avgprice);
(1.5)檢視輸出變數值
SELECT @avgprice;

2、建立儲存函式
(2.1)建立語句
CREATE FUNCTION func_name( func_parameter )
RETURNS type
[characteristic…] routine_body

func_name 儲存函式名稱
func_parameter 儲存過程的引數列表
RETURNS type 表示函式返回資料型別
(2.2)建立函式例子

CREATE FUNCTION nameByZip()
    RETURNS CHAR(50)
RETURN (SELECT s_name FROM tb_supplies WHERE s_call='45678' );
例子:
DELIMITER//
BEGIN
    CREATE FUNCTION returnAvgprice()
    RETURNS VARCHAR(50)
    RETURN(SELECT AVG(price) FROM tb_proceduretest);
END//
DELIMITER;

(2.3)呼叫儲存函式
SELECT returnAvgprice();

如果儲存函式中的RETURN語句返回一個型別不同於函式RETURNS字句中指定型別的值,返回值將被強制為恰當的型別
指定引數IN OUT INOUT 只對PROCEDURE是合法的(FUNCTION 總是預設為 IN)RETURNS 字句只能對FUNCTION 做指定 用來指定函式的返回型別
函式體必須包含一個RETURN value語句

3、變數的使用
(1)定義變數DECLARE
DECLARE var_name[,varname] data_type [DEFAULT value]
var_name區域性變數的名稱
DEFAULT value字句給變數提供一個預設的值 常數或表示式 沒有初始值為null
定義名稱為myParam變數 型別為INT 預設值100
DECLARE myParam INT DEFAULT 100;

4、為變數賦值
SET var_name = expr[,var_name = expr]…;
宣告3個變數 var1 var2 var3 資料型別為INT 使用SET為變數賦值
DECLARE var1 var2 var3 INT;
SET var1=10,var2=20;
SET var3=var1+var2;

SELECT … INTO 為一個或多個變數賦值
SELECT col_name[,…] INTO var_name[,…] table_expr;
#table_expr 表示查詢條件表示式

DECLARE fruitname CHAR(50);
DECLARE fruitprice DECIMAL(8,2);
SELECT f_name,f_price INTO fruitname,fruitprice
FROM tb_fruits
WHERE f_id=‘1’;

5、定義條件和處理程式
定義條件

DECLARE condition_name CONDITION FOR [condition_type]
[condition_type]:
SQLSTATE[VALUE] sqlstate_value|mysql_error_code

condition_name引數條件名稱
condition_type條件型別
sqlstate_value長度5的字串型別錯誤程式碼
mysql_error_code為數字型別錯誤程式碼
ERROR 1142(42000) sqlstate_value:42000 mysql_error_code:1142

DECLARE commond_not_allowed CONDITION FOR SQLSTATE ‘42000’;
DECLARE commond_not_allowed CONDITION FOR 1148;

定義處理程式
DECLARE handler_type HANDLER FOR condition_value[,…] sp_statement
handler_type:錯誤處理方式CONTINUE|EXIT|UNDO
CONTINUE 遇到錯誤不處理繼續執行
EXIT 遇到錯誤馬上退出
UNDO 遇到錯誤撤回之前的操作

condition_value: SQLSTATE[VALUE] sqlstate_value
SQLSTATE[VALUE] sqlstate_value包5個字元的字串錯誤值
condition_name 表示DECLARE CONDITION定義的錯誤條件名稱
SQLWARNING 匹配所有以01開頭的SQLSTATE錯誤程式碼
NOT FOUND 匹配所有以02開頭的SQLSTATE錯誤程式碼
SQLEXCEPTION 匹配所有沒有被SQLWARING或NOT FOUND捕獲的SQLSTATE錯誤
mysql_error_code 匹配數值型別錯誤程式碼

sp_statement 為程式語句段,表示在遇到錯誤定義是,需要執行的儲存過程或函式

定義處理程式的幾種方式
#方法1:捕獲sqlstate_value
DECLARE CONTINUE HANDLER FOR SQLSTATE ‘42S02’ SET @info=‘NO_SUCH_TABLE’;
#方法2:捕獲mysql_error_code
DECLARE CONTINUE HANDLER FOR 1146 SET @info=‘NO_SUCH_TABLE’;
#方法3:先定義條件,然後呼叫
DECLARE no_such_table CONDITION FOR 1146;
DECLARE CONTINUE HANDLER FOR no_such_table SET @info=‘NO_SUCH_TABLE’;
#方法4:使用SQLWARNING
DECLARE EXIT HANDLER FOR SQLWARNING SET @info=‘ERROR’;
#方法5:使用NOT FOUND
DECLARE EXIT HANDLER FOR NOT FOUND SET @info=‘NO_SUCH_TABLE’;
#方法6:使用SQLEXCEPTION
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info=‘NO_SUCH_TABLE’;

#定義條件和處理程式執行過程

CREATE TABLE tb_procedure(
    id INT PRIMARY KEY
);

DELIMITER //
CREATE PROCEDURE handlerDemo()
BEGIN
    DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2=1;
    SET @x=1;
    INSERT INTO tb_procedure VALUES(1);
    SET @x=2;
    INSERT INTO tb_procedure VALUES(1);
    SET @x=3;
END//

CREATE PROCEDURE handlerDemo()
BEGIN
    DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2=1;
    SET @x=1;
    INSERT INTO tb_test2(username,password) VALUES('c','123');
    SET @x=2;
    INSERT INTO tb_test2(username,password) VALUES('q','234');
    SET @x=3;
END//

DELIMITER ;

#呼叫儲存過程
CALL handlerDemo(); 結果:Query OK,0row affected 1 warning(0.00 sec)
#檢視呼叫過程結果
SELECT @x; 結果:@x=3;