一、概述
存储过程是一组为了完成某项特定功能的sql语句集,其实质上就是一段存储在数据库中的代码,他可以由声明式的sql语句(如CREATE,UPDATE,SELECT等语句)和过程式sql语句(如IF…THEN…ELSE控制结构语句)组成。存储过程思想上很简单,就是数据库 SQL 语言层面的代码封装与重用。
二、优缺点
优点
1、存储过程可以用流程控制语言编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算; 2、存储过程执行一次后,其执行规划就驻留在高速缓冲存储器中,以后的操作中只需要从高速缓冲器中调用已编译好的二进制代码执行即可,从而提高了系统性能。
缺点
存储过程,往往定制化于特定的数据库上,因为支持的编程语言不同。当切换到其他厂商的数据库系统时,需要重写原有的存储过程。
三、基本语法
1、创建
CREATE
[DEFINER = {
user | CURRENT_USER }
]
PROCEDURE 存储过程名
([proc_parameter
[,...]])
[characteristic
...] routine_body
[begin_label:
] BEGIN
[statement_list
]
……
END [end_label
]
IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量)
OUT输出参数:表示过程向调用者传出值
(可以返回多个值
)(传出值只能是变量)
INOUT输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| {
CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY {
DEFINER | INVOKER }
示例
mysql
> delimiter $$
mysql
> CREATE PROCEDURE delete_matches
(IN p_playerno
INTEGER)
-> BEGIN
-> DELETE FROM MATCHES
-> WHERE playerno
= p_playerno
;
-> END$$
Query OK
, 0 rows affected
(0.01 sec
)
mysql
> delimiter;
2、查看
select name
from mysql
.proc where db
='数据库名';
show procedure status where db
='数据库名';
3、删除
DROP PROCEDURE '数据库名'
四、应用示例
1、IN 输入参数
DELIMITER $$
CREATE PROCEDURE INPARAM_PRO
(IN PARAM_IN
INT)
BEGIN
SELECT PARAM_IN
;
SET PARAM_IN
= 2;
SELECT PARAM_IN
;
END$$
DELIMITER;
SET @PARAM_IN = 1;
CALL INPARAM_PRO
(@PARAM_IN);
SELECT @PARAM_IN;
CALL INPARAM_PRO
(1);
PARAM_IN
1
PARAM_IN
2
PARAM_IN
1
2、OUT输出参数
DELIMITER $$
CREATE PROCEDURE OUTPARAM_PRO
(OUT PARAM_OUT
VARCHAR(100))
BEGIN
SELECT PARAM_OUT
;
SET PARAM_OUT
= 'LOVE';
SELECT PARAM_OUT
;
END$$
DELIMITER;
SET @PARAM_OUT = 'hello';
CALL OUTPARAM_PRO
(@PARAM_OUT);
PARAM_OUT
NULL
PARAM_OUT
LOVE
3、INOUT输入输出参数
DELIMITER $$
CREATE PROCEDURE INOUTPARAM_PRO
(INOUT PARAM_INOUT
VARCHAR(100))
BEGIN
SELECT PARAM_INOUT
;
SET PARAM_INOUT
= 'QQ';
SELECT PARAM_INOUT
;
END$$
DELIMITER;
SET @PARAM_INOUT = 'WEIXIN';
CALL INOUTPARAM_PRO
(@PARAM_INOUT);
PARAM_INOUT
WEIXIN
PARAM_INOUT
QQ
4、声明变量
变量的声明使用declare,一句declare只声明一个变量,变量必须先声明后使用; 存储过程中变量的作用域,作用范围在begin和end块之间,end结束变量的作用范围即结束 变量可以通过set来赋值,也可以通过select into的方式赋值 传参变量是全局的,可以在多个块之间起作用
DELIMITER $$
CREATE PROCEDURE TEST_PRO
()
BEGIN
DECLARE final_var
VARCHAR(225);
SELECT CONCAT
('Hello',' ', ' MySQL') into final_var
;
SELECT final_var
;
END$$
DELIMITER;
CALL TEST_PRO
();
final_var
Hello MySQL
5、存储过程中使用流程语句
if-then-else 语句
DELIMITER $$
CREATE PROCEDURE TEST_PRO
(IN SCORE
INTEGER)
BEGIN
DECLARE SCORE_LEVEL
VARCHAR(20) DEFAULT '';
IF SCORE
<60 THEN
SET SCORE_LEVEL
= 'C';
ELSEIF SCORE
>=90 THEN
SET SCORE_LEVEL
= 'A';
ELSE
SET SCORE_LEVEL
= 'B';
END IF;
SELECT SCORE_LEVEL
;
END$$
DELIMITER;
SET @SCORE = 80;
CALL TEST_PRO
(@SCORE);
SCORE_LEVEL
B
CASE语句
DELIMITER
CREATE PROCEDURE TEST_PRO
(IN NUM
INTEGER, OUT VAR
VARCHAR(10) DEFAULT 'true')
BEGIN
CASE NUM
WHEN NUM
=0 THEN
SET VAR
= 'true';
ELSE
SET VAR
= 'false';
END CASE;
SELECT VAR
;
END
DELIMITER;
SET @NUM = 1;
SET @VAR = '';
CALL TEST_PRO
(@NUM, @VAR);
VAR
false
LOOP循环语句
CREATE TABLE `loop_test
` (
`id
` int(11) NOT NULL,
`test_column
` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
;
DELIMITER
CREATE PROCEDURE TEST_PRO
()
BEGIN
DECLARE i
int default 1;
loop_test:
LOOP
INSERT INTO loop_test
VALUES(i
, CONCAT
('test', i
));
SET i
= i
+1;
IF i
> 10 THEN
LEAVE loop_test
;
END IF;
END LOOP loop_test
;
END
DELIMITER;
CALL TEST_PRO
();
id test_column
1 test1
2 test2
3 test3
4 test4
5 test5
6 test6
7 test7
8 test8
9 test9
10 test10
REPEAT循环语句
DELIMITER
CREATE PROCEDURE TEST_PRO
()
BEGIN
DECLARE i
int default 0;
REPEAT
SELECT i
;
SET i
= i
+1;
UNTIL i
> 10 END REPEAT;
END
DELIMITER;
CALL TEST_PRO
();
输出i从
1到
10
WHILE 语句
DELIMITER
CREATE PROCEDURE TEST_PRO
()
BEGIN
DECLARE i
INT DEFAULT 5;
DECLARE COUNT
INT DEFAULT 0;
WHILE i
> 0 DO
SET COUNT
= COUNT
+ i
;
SET i
= i
-1;
END WHILE;
SELECT COUNT
;
END
DELIMITER;
CALL TEST_PRO
();
COUNT
15