简单地说,存储过程就是一条或者多条SQL语句的集合,可视为批文件,但是其作用不仅限于批处理。存储过程和存储函数都是为了实现特定的数据库操作或业务逻辑而创建的。选择使用哪种类型的存储过程取决于你的具体需求和场景。如果你需要执行复杂的数据库操作或业务逻辑,并且需要返回多个结果集或状态值,那么存储过程可能更适合。如果你需要执行简单的计算或数据转换操作,并且需要返回一个计算结果,那么存储函数可能更适合。
存储程序可以分为存储过程和函数。在MySQL中,创建存储过程和函数使用的语句分别是CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句来调用存储过程,只能用输出变量返回值。函数可以从语句外调用(引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。
创建存储过程,需要使用CREATE PROCEDURE语句,基本语法格式如下:
CREATE PROCEDURE sp_name ( [proc_parameter] )
[characteristics ...] routine_body
创建存储函数,需要使用CREATE FUNCTION语句,基本语法格式如下:
CREATE FUNCTION 函数名称 (参数1 数据类型, 参数2 数据类型)
RETURNS 返回类型
BEGIN
-- 函数体
END;
“DELIMITER //”语句的作用是将MySQL的结束符设置为//,因为MySQL默认的语句结束符号为分号‘;’。为了避免与存储过程中SQL语句结束符相冲突,需要使用DELIMITER改变存储过程的结束符,并以“END //”结束存储过程。存储过程定义完毕之后再使用“DELIMITER ;”恢复默认结束符。DELIMITER也可以指定其他符号作为结束符。
变量可以在子程序中声明并使用,这些变量的作用范围是在BEGIN…END程序中,本小节主要介绍如何定义变量和为变量赋值。
DELIMITER //
CREATE PROCEDURE MyProcedure()
BEGIN
-- 定义局部变量
DECLARE myVariable INT;
-- 为局部变量赋值
SET myVariable = 10;
-- 在存储过程中使用局部变量
SELECT name INTO myVariable;
END //
DELIMITER ;
DELIMITER //
CREATE PROCEDURE MyProcedure()
BEGIN
-- 定义局部变量
DECLARE myVariable INT;
-- 定义条件
IF myVariable = 10 THEN
-- 在满足条件时执行的代码块
SELECT 'myVariable is 10';
ELSE
-- 在不满足条件时执行的代码块
SELECT 'myVariable is not 10';
END IF;
-- 定义处理程序
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
-- 在发生异常时执行的代码块
ROLLBACK; -- 回滚事务
RESIGNAL; -- 重新抛出异常
END;
-- 执行可能引发异常的代码
-- ...
END //
DELIMITER ;
查询语句可能返回多条记录,如果数据量非常大,需要在存储过程和储存函数中使用光标来逐条读取查询结果集中的记录。应用程序可以根据需要滚动或浏览其中的数据。在MySQL中,你可以在存储过程中使用光标来遍历查询结果集。光标允许你逐行处理查询返回的结果,并对每一行执行特定的操作。
DELIMITER //
CREATE PROCEDURE MyProcedure()
BEGIN
-- 声明光标
DECLARE done INT DEFAULT FALSE;
DECLARE myColumn VARCHAR(255);
DECLARE cur CURSOR FOR SELECT column_name FROM my_table;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- 打开光标
OPEN cur;
-- 使用光标遍历结果集
read_loop: LOOP
使用光标
FETCH cur INTO myColumn;
IF done THEN
LEAVE read_loop;
END IF;
-- 在这里执行对每一行的操作,例如:
SELECT myColumn;
END LOOP;
-- 关闭光标
CLOSE cur;
END //
DELIMITER ;
MySQL中用来构造控制流程的语句有IF语句、CASE语句、LOOP语句、LEAVE语句、ITERATE语句、REPEAT语句和WHILE语句。
1 IF语句:用于根据条件判断执行不同的代码块。
IF condition THEN
-- 执行代码块
END IF;
2 CASE语句:用于根据条件选择不同的执行路径。
CASE
WHEN condition1 THEN -- 执行代码块1
WHEN condition2 THEN -- 执行代码块2
...
ELSE -- 默认执行代码块
END CASE;
3 LOOP语句:用于重复执行一段代码。
LOOP
-- 重复执行的代码块
END LOOP;
4 LEAVE语句:用于跳出循环。
LEAVE loop_name; -- 跳出指定的循环
5 WHILE语句:用于在满足条件时重复执行一段代码。
WHILE condition DO
-- 重复执行的代码块
END WHILE;
6 REPEAT语句:用于重复执行一段代码,直到条件不再满足
REPEAT
-- 重复执行的代码块
UNTIL condition -- 结束循环的条件
END REPEAT;
7 ITERATE语句
ITERATE语句将执行顺序转到语句段开头处,ITERATE只可以出现在LOOP、REPEAT和WHILE语句内。ITERATE的意思为“再次循环”,label参数表示循环的标志。ITERATE语句必须跟在循环标志前面。
ITERATE label
存储过程必须使用CALL语句调用,并且存储过程和数据库相关,如果要执行其他数据库中的存储过程,需要指定数据库名称,例如CALL dbname.procname。
存储过程是通过CALL语句进行调用的,语法如下:
CALL sp_name([parameter[,...]])
在MySQL中,存储函数的使用方法与MySQL内部函数的使用方法是一样的。
SHOW PROCEDURE STATUS;
SHOW PROCEDURE STATUS WHERE Db = '数据库名称';
SHOW PROCEDURE STATUS WHERE Name = '存储过程名称';
SHOW CREATE PROCEDURE 存储过程名称;
使用ALTER语句可以修改存储过程或函数的特性,
ALTER PROCEDURE procedure_name
BEGIN
-- 修改后的存储过程定义
SELECT * FROM table_name WHERE column_name = 'value';
END;
5 删除存储过程和函数
删除存储过程:
DROP PROCEDURE procedure_name;
删除函数:
DROP FUNCTION function_name;