mysql8學習筆記18--儲存過程和函式
阿新 • • 發佈:2020-08-09
•create procedure用來建立儲存過程,create function用來建立函式
• 函式與儲存過程最大的區別就是函式呼叫有返回值,呼叫儲存過程用call語句,而呼叫函式就直接引用函式名+引數即可
• Definer和sql security子句指定安全環境 • Definder是MySQL的特殊的訪問控制手段,當資料庫當前沒有這個使用者許可權時,執行儲存過程可能會報錯 • sql secuirty的值決定了呼叫儲存過程的方式,取值 :definer(預設)或者invokerdefiner:在執行儲存過程前驗證definer對應的使用者如:[email protected]是否存在,以及是否具有執行儲存過程的許可權,若沒有則報錯invoker:在執行儲存過程時判斷inovker即呼叫該儲存過程的使用者是否有相應許可權,若沒有則報錯 • IN,OUT,INOUT三個引數前的關鍵詞只適用於儲存過程,對函式而言所有的引數預設都是輸入引數 • IN輸入引數用於把數值傳入到儲存過程中;OUT輸出引數將數值傳遞到呼叫者,初始值是NULL;INOUT輸入輸出引數把資料傳入到儲存過程,在儲存過程中修改之後再傳遞到呼叫者 • Delimiter命令是改變語句的結束符,MySQL預設的結束符為;號,由於procedure和function中的;號並不代表建立的結束,所以要替換成另外的結束符以便表示建立的結束 • Rontine_body子句可以包含一個簡單的SQL語句,也可以包含多個SQL語句,通過begin…end將這多個SQL語句包含在一起 • MySQL儲存過程和函式中也可以包含類似create和drop等DDL語句 • Comment子句用來寫入對儲存過程和函式的註釋 • Language子句用來表示此儲存過程和函式的建立語言 • 儲存過程和函式被標註為deterministic表明當輸入相同的引數是會返回相同的結果,反之如果是not deterministic則表示相同引數不會是相同結果,預設是not deterministic • 相關屬性短語只有諮詢含義,並不是強制性的約束 • Contains sql表明此儲存過程或函式不包含讀或者寫資料的語句,這是預設屬性 • NO SQL表示此儲存過程或函式不包含SQL語句 • Reads sql data表示此儲存過程包含諸如select的查詢資料的語句,但不包含插入或刪除資料的語句 • Modifies sql data表示此儲存過程包含插入或刪除資料的語句 • Drop procedure/function語句用來刪除指定名稱的儲存過程或函式 • If exists關鍵詞用來避免在刪除一個本身不存在的儲存過程或函式時,MySQL返回錯誤 • Begin…end語句通常出現在儲存過程、函式和觸發器中,其中可以包含一個或多個語句,每個語句用;號隔開建立儲存過程:
/*在建立之前如果存在同名儲存過程,則刪除*/ drop PROCEDURE if EXISTS create_student; /*修改分分隔符為;;*/ delimiter ;; create PROCEDURE create_student (OUT new_stuid INT,IN new_name VARCHAR(10),IN birth date,IN addr VARCHAR(50),IN gender VARCHAR(10),IN sub_jct VARCHAR(10)) BEGIN /*為new_stuid宣告變數*/ DECLARE new_stuid int; DECLARE stu_sexint; select max(stuid) into new_stuid from tb_student2; set new_stuid = new_stuid +1; case stu_sex WHEN gender='男生' THEN SET stu_sex=0; WHEN gender='女生' THEN SET stu_sex=1; else set stu_sex=2; END case; /*插入資料到tb_student2*/ insert INTO tb_student2(stuid,stuname,stusex,stubirth,stuaddr,collid) VALUES(new_stuid,new_name,stu_sex,birth,addr,2); END;; delimiter ;
呼叫儲存過程:
mysql> call create_student(@new_stuid,"王超人",'1999-03-04','廣東深圳','男生','計算機'); Query OK, 1 row affected (0.08 sec) mysql> select @new_stuid; +------------+ | @new_stuid | +------------+ | NULL | +------------+ 1 row in set (0.00 sec) mysql> select * from tb_student2; +-------+--------------+--------+------------+--------------+--------+ | stuid | stuname | stusex | stubirth | stuaddr | collid | +-------+--------------+--------+------------+--------------+--------+ | 1001 | 張三 | 0 | 1990-03-04 | ABCabc | 1 | | 1002 | 季墨 | 0 | 1992-02-02 | 湖南長沙 | 1 | | 1033 | 王語嫣 | 1 | 1989-12-03 | 四川成都 | 1 | | 1378 | 紀嫣然 | 1 | 1995-08-12 | 四川綿陽 | 1 | | 1572 | 張子文 | 0 | 1993-07-19 | 陝西咸陽 | 1 | | 1954 | 張學友 | 0 | 1994-09-20 | 福建莆田 | 1 | | 2035 | 東方不敗 | NULL | 1988-06-30 | NULL | 2 | | 3011 | 金大牙 | 0 | 1985-12-12 | 福建莆田 | 3 | | 3755 | 豬腳 | 0 | 1993-01-25 | NULL | 3 | | 3923 | 楊不悔 | 1 | 1985-04-17 | 四川成都 | 3 | | 3924 | 王超人 | 2 | 1999-03-04 | 廣東深圳 | 2 | | 3925 | 王超人2 | 2 | 1999-03-04 | 廣東深圳 | 2 | +-------+--------------+--------+------------+--------------+--------+ 12 rows in set (0.00 sec) mysql>
把上面的例子改造成函式
/*在建立之前如果存在同名函式,則刪除*/ drop FUNCTION if EXISTS create_student_function; /*修改分分隔符為;;*/ delimiter ;; create FUNCTION create_student_function (new_name VARCHAR(10),birth date,addr VARCHAR(50),gender VARCHAR(10),sub_jct VARCHAR(10)) RETURNS INT BEGIN /*為new_stuid宣告變數*/ DECLARE new_stuid int; DECLARE stu_sex int; select max(stuid) into new_stuid from tb_student2; set new_stuid = new_stuid +1; case stu_sex WHEN gender='男生' THEN SET stu_sex=0; WHEN gender='女生' THEN SET stu_sex=1; else set stu_sex=2; END case; /*插入資料到tb_student2*/ insert INTO tb_student2(stuid,stuname,stusex,stubirth,stuaddr,collid) VALUES(new_stuid,new_name,stu_sex,birth,addr,2); RETURN new_stuid; END;; delimiter ;
呼叫函式
mysql> select create_student("王超人",'1999-03-04','廣東深圳','男生','計算機'); ERROR 1305 (42000): FUNCTION school.create_student does not exist mysql> select create_student_function("王超人",'1999-03-04','廣東深圳','男生','計算機'); +---------------------------------------------------------------------------------------+ | create_student_function("王超人",'1999-03-04','廣東深圳','男生','計算機') | +---------------------------------------------------------------------------------------+ | 3926 | +---------------------------------------------------------------------------------------+ 1 row in set, 8 warnings (0.09 sec) mysql> select create_student_function("王超人",'1999-03-04','廣東深圳','男生','計算機'); +---------------------------------------------------------------------------------------+ | create_student_function("王超人",'1999-03-04','廣東深圳','男生','計算機') | +---------------------------------------------------------------------------------------+ | 3927 | +---------------------------------------------------------------------------------------+ 1 row in set (0.06 sec) mysql> select create_student_function("王超人",'1999-03-04','廣東深圳','男生','計算機'); +---------------------------------------------------------------------------------------+ | create_student_function("王超人",'1999-03-04','廣東深圳','男生','計算機') | +---------------------------------------------------------------------------------------+ | 3928 | +---------------------------------------------------------------------------------------+ 1 row in set (0.05 sec) mysql>
檢視所有儲存例程:
mysql> show procedure status like '%create_student%'; +--------+----------------+-----------+---------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ | Db | Name | Type | Definer | Modified | Created | Security_type | Comment | character_set_client | collation_connection | Database Collation | +--------+----------------+-----------+---------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ | school | create_student | PROCEDURE | root@% | 2020-08-08 23:08:22 | 2020-08-08 23:08:22 | DEFINER | | utf8 | utf8_general_ci | utf8_bin | +--------+----------------+-----------+---------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ 1 row in set (0.00 sec) mysql> show function status like '%create%'; +--------+-------------------------+----------+---------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ | Db | Name | Type | Definer | Modified | Created | Security_type | Comment | character_set_client | collation_connection | Database Collation | +--------+-------------------------+----------+---------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ | school | create_student_function | FUNCTION | root@% | 2020-08-09 16:47:51 | 2020-08-09 16:47:51 | DEFINER | | utf8 | utf8_general_ci | utf8_bin | +--------+-------------------------+----------+---------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+ 1 row in set (0.01 sec) mysql>
檢視儲存例程建立語句
mysql> show create procedure create_student; +----------------+-----------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ | Procedure | sql_mode | Create Procedure | character_set_client | collation_connection | Database Collation | +----------------+-----------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ | create_student | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | CREATE DEFINER=`root`@`%` PROCEDURE `create_student`(OUT new_stuid INT,IN new_name VARCHAR(10),IN birth date,IN addr VARCHAR(50),IN gender VARCHAR(10),IN sub_jct VARCHAR(10)) BEGIN /*為new_stuid宣告變數*/ DECLARE new_stuid int; DECLARE stu_sex int; select max(stuid) into new_stuid from tb_student2; set new_stuid = new_stuid +1; case stu_sex WHEN gender='男生' THEN SET stu_sex=0; WHEN gender='女生' THEN SET stu_sex=1; else set stu_sex=2; END case; /*插入資料到tb_student2*/ insert INTO tb_student2(stuid,stuname,stusex,stubirth,stuaddr,collid) VALUES(new_stuid,new_name,stu_sex,birth,addr,2); END | utf8 | utf8_general_ci | utf8_bin | +----------------+-----------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ 1 row in set (0.00 sec) mysql> show create function create_student_function; +-------------------------+-----------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ | Function | sql_mode | Create Function | character_set_client | collation_connection | Database Collation | +-------------------------+-----------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ | create_student_function | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | CREATE DEFINER=`root`@`%` FUNCTION `create_student_function`(new_name VARCHAR(10),birth date,addr VARCHAR(50),gender VARCHAR(10),sub_jct VARCHAR(10)) RETURNS int(11) BEGIN /*為new_stuid宣告變數*/ DECLARE new_stuid int; DECLARE stu_sex int; select max(stuid) into new_stuid from tb_student2; set new_stuid = new_stuid +1; case stu_sex WHEN gender='男生' THEN SET stu_sex=0; WHEN gender='女生' THEN SET stu_sex=1; else set stu_sex=2; END case; /*插入資料到tb_student2*/ insert INTO tb_student2(stuid,stuname,stusex,stubirth,stuaddr,collid) VALUES(new_stuid,new_name,stu_sex,birth,addr,2); RETURN new_stuid; END | utf8 | utf8_general_ci | utf8_bin | +-------------------------+-----------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+ 1 row in set (0.00 sec) mysql>
儲存例程刪除
mysql> drop function create_student_function; Query OK, 0 rows affected (0.02 sec) mysql> show function status like '%create%'; Empty set (0.00 sec) mysql> drop procedure create_student; Query OK, 0 rows affected (0.03 sec) mysql> show procedure status like '%create_student%'; Empty set (0.00 sec) mysql>
• 標籤label可以加在begin…end語句以及loop, repeat和while語句
• 語句中通過iterate和leave來控制流程,iterate表示返回指定標籤位置,leave表示跳出標籤使用label標籤
drop PROCEDURE if EXISTS test_procedure; delimiter // CREATE procedure test_procedure(in p1 int,out p2 int) BEGIN label1:LOOP set p1 = p1 + 1; if p1 < 10 then ITERATE label1;END if; LEAVE label1; END LOOP label1; set p2=p1; END; //
除錯下:
mysql> call test_procedure(5,@p2); Query OK, 0 rows affected (0.00 sec) mysql> select @p2; +------+ | @p2 | +------+ | 10 | +------+ 1 row in set (0.00 sec) mysql>Declare語句 • Declare語句通常用來宣告本地變數、遊標、條件或者handler • Declare語句只允許出現在begin … end語句中而且必須出現在第一行 • Declare的順序也有要求,通常是先宣告本地變數,再是遊標,然後是條件和handler 儲存過程中的變數 • 本地變數可以通過declare語句進行宣告 • 聲明後的變數可以通過select … into var_list進行賦值,或者通過set語句賦值,或者通過定義遊標並使用fetch … into var_list賦值 • 通過declare宣告變數方法
• 使用default指定變數的預設值,如果沒有指定預設值則初始值為NULL
• Type指明該變數的資料型別 • 宣告的變數作用範圍為被宣告的begin … end語句塊之間 • 宣告的變數和被引用的資料表中的欄位名要區分開來變數宣告在上面的例子裡用到了,遊標後面學到再寫。