第十章 儲存過程和函式
10.1 建立儲存過程和函式
MySQL中建立儲存過程和函式使用的語句分別是:
CREATE PROCEDURE
和CREATE FUNCTION
。
注意:使用CALL語句來呼叫儲存過程,只能用輸出變數返回值。
建立儲存過程基本句法:
CREATE PROCEDURE sp_name([proc_parameter]) [characteristics...] routine_body;
CREATE PROCEDURE:用來建立儲存函式的關鍵字;
sp_name:儲存過程的名稱;
proc_parameter:指定儲存過程的引數列表。
(列表形式如下:[IN|OUT|INOUT] param_name type
characteristics:指定儲存過程的特性。
下面程式碼演示了儲存過程的內容,名稱為AvgFruitPrice,返回所有水果的平均價格,輸入程式碼如下:
mysql> CREATE PROCEDURE Proc()
-> BEGIN
-> SELECT * FROM fruits;
-> END //
Query OK, 0 rows affected (0.25 sec)
10.1.2 建立儲存函式
基本語法格式:
CREATE FUNCTION func_name([func_parameter]) RETURNS type [characteristics...] routine_body;
例:建立儲存函式,名稱為NameByZip,該函式返回SELECT語句查詢結果,數值型別為字串型:
mysql> CREATE FUNCTION NameByZip()
-> RETURNS CHAR(50)
-> RETURN (SELECT s_name FROM suppliers WHERE s_call='48075');
-> //
Query OK, 0 rows affected (0.08 sec)
注:DELIMITER ;
將結束符換回來。
10.1.3 變數的使用
變數可以在子程式中宣告並使用,這些變數的作用範圍是在BEGIN…END程式中。
1.定義變數
句法:DECLARE var_name[,varname]...date_type[DEFAULT value]
2.為變數賦值
句法:
SET var_name=expr [,var_name=expr]...;
10.1.4 定義條件和處理程式
1.定義條件
句法:
DECIMAL condition_name CONDITION [condition_type] [condition_type]: SQLSTATE[VALUE] sqlstate_value | mysql_error_code
例:定義“ERROR 1148(42000)”錯誤,名稱為command_not_allowed。可以用兩種不同的方法來定義:
//方法一:使用salstate_value
DECLARE command_not_allowed CONDITION FOR SQLSTATE '42000';
//方法二:使用mysql_error_code
DELARE command_not_allow CONDITION FOR 1148
2.定義處理程式
句法:
DELARE handler_type HANDLER FOR condition_value[,...] sp_statement
handler_type:
CONTINUE | EXIT | UNDO
condition_value:
SQLSTATE[VALUE]sqlstate_value
|condition_name
|SQLWARNING
|NOT FOUND
|SQLEXCEPTION
|mysql_error_code
handler_type(錯誤處理方式):
CONTINUE:遇到錯誤不處理;
EXIT:遇到錯誤馬上退出;
UNDO:遇到錯誤後撤回之前的操作,MySQL中暫時不支援這樣的操作。
condition_value:表示錯誤型別。
sp_statement引數為程式語句段,表示在遇到錯誤時,需要執行的儲存過程或函式。
10.1.5 游標的使用
1.宣告游標
句法:
DECLARE cursor_name CURSOR FOR select_statement
cursor_name引數表示游標的名稱;
select_statement引數表示SELECT語句的內容,返回用於建立游標的結果集。
2.開啟游標
句法:OPEN cursor_name{游標名稱}
3.關閉游標
句法:CLOSE cursor_name{游標名稱}
10.1.6 流程控制的使用
- IF語句
程式碼示例:
IF val IS NULL
THEN SELECT 'val is NULL';
ELSE SELECT 'val is not NULL';
END IF;
- CASE語句
CASE val
WHEN 1 THEN SELECT 'val is 1’;
WHEN 2 THEN SELECT 'val is 2’;
ELSE SELECT 'val is not 1 or 2’;
END CASE
- LOOP語句
例:
DELARE id INT DEFAULT 0;
add_loop:LOOP
SET id=id+1;
IF id>=10 THEN LEAVE add_loop;
END IF;
END LOOP add_loop;
- LEAVE語句
例:
add_num:LOOP
SET @[email protected]+1;
IF @count =50 THEN LEAVE add_num;
END LOOP add_num;
- ITERATE語句
語句將執行順序轉到語句段開頭處。
ITERATE語句只可以出現在LOOP、REPEATE和WHILE語句內。 - REPEAT語句
- WHILE語句
10.2 呼叫儲存過程和函式
10.2.1 呼叫儲存過程
CALL sp_name([parameter[,...]])
10.2.2 呼叫儲存函式
使用SELECT.
10.3檢視儲存過程和函式
10.3.1 SHOW STATUS語句檢視儲存過程和函式的狀態
SHOW {PROCEDURE|FUNCTION} STATUS [LIKE 'pattern']
程式碼示例:
SHOW PROCEDURE STATUS LIKE 'C%'\G;
*************************** 1. row ***************************
Db: sys
Name: create_synonym_db
Type: PROCEDURE
Definer: [email protected]
Modified: 2018-09-28 18:59:36
Created: 2018-09-28 18:59:36
Security_type: INVOKER
Comment:
Description
Takes a source database name and synonym name, and then creates the
synonym database with views that point to all of the tables within
the source database.
Useful for creating a "ps" synonym for "performance_schema",
or "is" instead of "information_schema", for example.
Parameters
in_db_name (VARCHAR(64)):
The database name that you would like to create a synonym for.
in_synonym (VARCHAR(64)):
The database synonym name.
Example
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.00 sec)
mysql> CALL sys.create_synonym_db('performance_schema', 'ps');
+---------------------------------------+
| summary |
+---------------------------------------+
| Created 74 views in the `ps` database |
+---------------------------------------+
1 row in set (8.57 sec)
Query OK, 0 rows affected (8.57 sec)
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| ps |
| sys |
| test |
+--------------------+
6 rows in set (0.00 sec)
mysql> SHOW FULL TABLES FROM ps;
+------------------------------------------------------+------------+
| Tables_in_ps | Table_type |
+------------------------------------------------------+------------+
| accounts | VIEW |
| cond_instances | VIEW |
| events_stages_current | VIEW |
| events_stages_history | VIEW |
...
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: utf8_general_ci
1 row in set (0.27 sec)
ERROR:
No query specified
10.3.2 SHOW CREATE語句檢視儲存過程和函式的定義
除了SHOW STATUS之外,MySQL還可以使用SHOW CREATE語句檢視儲存過程和函式的狀態。
SHOW CREATE {PROCEDURE | FUNCTION} sp_name
例:
mysql> SHOW CREATE FUNCTION test.CountPro\G;
10.3.3 從information_schema.Routines表中檢視儲存過程和函式的資訊
語法:
SELECT * FROM information_schema.Rountines WHERE ROUNTINE_NAME='sp_name'
;
10.4 修改儲存過程和函式
ALTER {PROCEDURE | FUNCTION} sp_name[characteric...]
10.5 刪除儲存過程和函式
DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name
10.6 綜合案例
01 建立一個名為sch的資料表,並向表中插入資料
mysql> CREATE TABLE sch(
-> id INT,
-> name VARCHAR(50),
-> glass VARCHAR(50)
-> );
Query OK, 0 rows affected (0.58 sec)
mysql> INSERT INTO sch VALUES(1,'xiaoming','glass1'),
-> (2,'xiaojun','glass2');
Query OK, 2 rows affected (0.11 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> DESC sch;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(50) | YES | | NULL | |
| glass | varchar(50) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.04 sec)
mysql> SELECT * FROM sch;
+------+----------+--------+
| id | name | glass |
+------+----------+--------+
| 1 | xiaoming | glass1 |
| 2 | xiaojun | glass2 |
+------+----------+--------+
2 rows in set (0.00 sec)
02建立一個可以統計表格內記錄條數的儲存函式,函式名為count_sch
mysql> DELIMITER //
mysql> CREATE FUNCTION count_sch()
-> RETURNS INT
-> RETURN(SELECT COUNT(*) FROM sch);
-> //
Query OK, 0 rows affected (0.10 sec)
mysql> SELECT count_sch()//
+-------------+
| count_sch() |
+-------------+
| 2 |
+-------------+
1 row in set (0.18 sec)
03建立一個儲存過程add_id在同時使用前面建立的儲存函式返回表sch中的記錄數,計算表中所以的id之和
mysql> DELIMITER //
mysql> CREATE PROCEDURE add_id(out count INT)
-> BEGIN
-> DECLARE itmp INT;
-> DECLARE cur_id CURSOR FOR SELECT id FROM sch;
-> DECLARE EXIT HANDLER FOR NOT FOUND CLOSE cur_id;
-> SELECT count_sch() INTO count;
-> SET @sum=0;
-> OPEN cur_id;
-> REPEAT
-> FETCH cur_id INTO itmp;
-> IF itmp<10
-> THEN SET @[email protected]+itmp;
-> END IF;
-> UNTIL 0 END REPEAT;
-> CLOSE cur_id;
-> END //
Query OK, 0 rows affected (0.10 sec)
mysql> SELECT @a,@sum //
+------+------+
| @a | @sum |
+------+------+
| NULL | NULL |
+------+------+
1 row in set (0.00 sec)