(2021.12.19 Sat)
SQL语句需要先编译再执行,存储过程(stored procedure)是完成了特定功能的SQL语句集合,经过编译保存在数据库中。用户可以通过名字调用和执行存储过程,并可以传递参数,和返回数据。
存储过程是可编程的函数,可以简单理解为是在数据库中实现的面向对象中的方法。
创建存储过程
创建过程伪代码
CREATE PROCEDURE ([[IN | OUT | INOUT] arg_name arg_type[, arg_name1 arg_type1])
BEGIN
END
对于MySQL,还需要加入DELIMITER
关键词
DELIMITER &&
CREATE PROCEDURE ([[IN | OUT | INOUT] arg_name arg_type[, arg_name1 arg_type1])
BEGIN
END &&
DELIMITER;
说明:
- procedure_name: 过程名
- IN | OUT | OUTIN: 参数传递方式,
IN
表示调用者向过程传入的参数,OUT
表示过程返回给调用者的参数/结果,OUTIN
表示向过程传递变量也从过程返回变量。 - arg_name & arg_type:传入或传出的变量名与类型
- BEGIN...END:过程主体
- declaration_section:主体的声明变量部分
- execution_section:函数执行部分代码
声明部分
声明部分的格式如下
DECLARE
[DEFAULT ];
DECLARE net_pay FLOAT(9,2) DEFAULT 0;
DECLARE id_name INT DEFAULT 0;
DECLARE dt DATETIME DEFAULT '2021-12-19 11:41:30';
DECLARE vv VARCHAR(255) DEFAULT 'This is a stored procedure demo.';
执行部分格式
执行部分即SQL的指令。除了常规的SQL命令,可使用IF-ELSE
,CASE-WHEN
,WHILE-DO
,REPEAT-UNTIL-END
,LOOP-END
语句。这些循环或判断结构可结合LEAVE
指令用来结束结构。同时注意到,BEGIN-END
结构可以嵌套。
BEGIN-END
结构可以被贴标签。
如
label_1: BEGIN
DECLARE var1 int DEFAULT 0;
SELECT var1;
END label_1;
判断和循环语句的格式
WHILE-DO...END-WHILE
DELIMITER //
CREATE PROCEDURE proc1 ()
BEGIN
DECLEAR var INT;
SET var = 7;
WHILE var < 6 DO
INSERT INTO specific_table VALUES (var);
SET var = var + 1;
END WHILE;
END;
//
DELIMITER;
REPEAT...UNTIL...END REPEAT,该命令与WHILE
不同的是先运行,后检查运行条件。
DELIMITER //
CREATE PROCEDURE proc2 ()
BEGIN
DECLEAR var INT;
SET var = 5;
REPEAT
INSERT INTO specific_table VALUE (var);
SET var = 6;
UNTIL var >= 7;
END REPEAT;
END;
//
DELIMITER;
LOOP
DELIMITER//
CREATE PROCEDURE proc ()
BEGIN
DECLEAR var INT;
SET var = 4;
loop_label: LOOP
INSERT INTO specific_table VALUES (var);
SET var = var + 1;
IF var >= 6
LEAVE loop_label;
END IF;
END LOOP;
END;
//
DELIMITER
IF-ELSE-THEN语句
DELIMITER //
CREATE PROCEDURE proc (IN para INT)
BEGIN
DECLEAR var INT;
SET var = para + 6;
IF para > 0 THEN
INSERT INTO specific_table VALUES (var);
ELSE
INSERT INTO specific_table VALUES (var-para);
END IF;
END;
//
DELIMITER;
CASE-WHEN-THEN-ELSE语句
DELIMITER //
CREATE PROCEDURE proc4 (IN parameter INT)
BEGIN
DECLARE var INT;
SET var=parameter+1;
CASE var
WHEN 0 THEN
INSERT INTO t VALUES (17);
WHEN 1 THEN
INSERT INTO t VALUES (18);
ELSE
INSERT INTO t VALUES (19);
END CASE ;
END ;
//
DELIMITER ;
ITERATE迭代通过引用复合语句的label,来从新开始复合语句。
#ITERATE
DELIMITER //
CREATE PROCEDURE proc()
BEGIN
DECLARE v INT;
SET v=0;
LOOP_LABLE:LOOP
IF v=3 THEN
SET v=v+1;
ITERATE LOOP_LABLE;
END IF;
INSERT INTO t VALUES(v);
SET v=v+1;
IF v>=5 THEN
LEAVE LOOP_LABLE;
END IF;
END LOOP;
END;
//
DELIMITER ;
变量作用域
分隔符DELIMITER
注意DELIMITER//
和DELIMITER;
两句,MySQL默认以";"为分隔 符,如果没有声明分割符,编译器会把存储过程当成SQL语句进行处理,则存储过程的编译过程会报错,所以要事先用DELIMITER
关键字声明当前段分隔符,这样MySQL才会将";"当做存储过程中的代码,不会执行这些代码,用完了之后要把分隔符还原。
调用存储过程
在mysql console中调用格式如下
mysql -> CALL proc_name();
如果调用时需要传入参数或传出参数,需要提前声明,注意在console中变量名前需要加@
。
变量赋值部分的格式如下
SET @
= ;
or
SELECTINTO @ ;
SET @var = 100; // 赋值
SELECT 'this is a test string' INTO @char_var;
SELECT @var; // 选定和返回数值变量
SELECT @char_var; // 选定和返回字符变量
注意,在存储过程的执行部分调用时不需要@
符号,直接使用变量名即可。在mysql console需要有@
标识符。
mysql -> SET @var = 1;
mysql -> CALL proc_name(@var);
存储过程的查询
SELECT name FROM mysql.proc WHERE db = ;
SELECT routine_name FROM information_schema.routines WHERE routine_schema = ;
SHOW PROCEDURE STATUS WHERE db = ;
#查看存储过程详细信息
SHOW CREATE PROCEDURE 数据库.存储过程名;
存储过程的修改和删除
ALTER PROCEDURE 更改用CREATE PROCEDURE 建立的预先指定的存储过程,其不会影响相关存储过程或存储功能。
ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...]
characteristic:
{ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'
变量解释:
- sp_name参数表示存储过程或函数的名称;
- characteristic参数指定存储函数的特性。
- CONTAINS SQL表示子程序包含SQL语句,但不包含读或写数据的语句;
- NO SQL表示子程序中不包含SQL语句;
- READS SQL DATA表示子程序中包含读数据的语句;
- MODIFIES SQL DATA表示子程序中包含写数据的语句。
- SQL SECURITY { DEFINER | INVOKER }指明谁有权限来执行,* DEFINER表示只有定义者自己才能够执行;INVOKER表示调用者可以执行。
COMMENT 'string'是注释信息。
删除
DROP PROCEDURE [proc_name1[, proc_name2...]];