mysql菜鸟教程
14.3 存储过程入门
存储过程是数据库中一个非常强大的功能,它允许你将一系列 SQL 语句封装成一个可重复调用的模块。如果说视图是“保存的查询”,那么存储过程就是“保存的程序”。通过存储过程,你可以实现复杂的业务逻辑,提高代码复用性和执行效率。
一、什么是存储过程?
存储过程(Stored Procedure) 是一组预编译的 SQL 语句,它们被存储在数据库服务器中,并可以通过名称被调用执行。存储过程可以接受参数、声明变量、进行条件判断和循环控制,甚至可以返回结果集。
为什么使用存储过程?
二、存储过程的基本语法
创建存储过程
DELIMITER // CREATE PROCEDURE 过程名(参数列表) BEGIN -- SQL 语句体 END // DELIMITER ;
DELIMITER:MySQL 默认以分号 ; 作为语句结束符,但在存储过程体内会包含多条 SQL 语句,所以需要临时改变分隔符,以便 MySQL 将整个存储过程视为一个完整的语句。
参数列表:可以包含零个或多个参数,每个参数由模式(IN/OUT/INOUT)、参数名和类型组成。
BEGIN ... END:包裹存储过程的语句体,可以包含多个 SQL 语句和逻辑控制。
调用存储过程
CALL 过程名(参数值列表);
删除存储过程
DROP PROCEDURE [IF EXISTS] 过程名;
查看存储过程
SHOW PROCEDURE STATUS WHERE db = '数据库名'; SHOW CREATE PROCEDURE 过程名;
三、参数类型
存储过程的参数有三种模式:
示例
-- 创建带 IN 参数的存储过程 DELIMITER // CREATE PROCEDURE GetEmployeeById(IN emp_id INT) BEGIN SELECT * FROM employees WHERE id = emp_id; END // DELIMITER ; -- 调用 CALL GetEmployeeById(1); -- 创建带 OUT 参数的存储过程 DELIMITER // CREATE PROCEDURE CountEmployees(OUT total INT) BEGIN SELECT COUNT(*) INTO total FROM employees; END // DELIMITER ; -- 调用 CALL CountEmployees(@emp_count); SELECT @emp_count; -- 查看输出变量的值
四、变量声明与使用
在存储过程中,可以使用 DECLARE 语句声明局部变量,也可以使用用户定义的变量(以 @ 开头)。
局部变量
作用域在 BEGIN ... END 块内。
必须在语句体的开头声明。
使用 SET 或 SELECT ... INTO 赋值。
DELIMITER // CREATE PROCEDURE CalculateBonus() BEGIN DECLARE avg_salary DECIMAL(10,2); DECLARE bonus DECIMAL(10,2); SELECT AVG(salary) INTO avg_salary FROM employees; SET bonus = avg_salary * 0.1; SELECT avg_salary, bonus; END // DELIMITER ;
五、流程控制
存储过程支持常见的流程控制语句,如 IF、CASE、循环等。
IF 语句
IF 条件 THEN 语句; ELSEIF 条件 THEN 语句; ELSE 语句; END IF;
示例:
DELIMITER // CREATE PROCEDURE CheckSalary(IN emp_id INT) BEGIN DECLARE emp_salary DECIMAL(10,2); SELECT salary INTO emp_salary FROM employees WHERE id = emp_id; IF emp_salary > 10000 THEN SELECT '高薪' AS level; ELSEIF emp_salary > 5000 THEN SELECT '中薪' AS level; ELSE SELECT '低薪' AS level; END IF; END // DELIMITER ;
CASE 语句
CASE 表达式 WHEN 值1 THEN 语句; WHEN 值2 THEN 语句; ELSE 语句; END CASE;
循环
MySQL 支持 WHILE、REPEAT 和 LOOP 循环。
WHILE 循环:
WHILE 条件 DO 语句; END WHILE;
REPEAT 循环:
REPEAT 语句; UNTIL 条件 END REPEAT;
LOOP 循环(需配合 LEAVE 退出):
label: LOOP 语句; IF 条件 THEN LEAVE label; END IF; END LOOP label;
示例:生成连续数字
DELIMITER // CREATE PROCEDURE GenerateNumbers(IN max_num INT) BEGIN DECLARE i INT DEFAULT 1; WHILE i <= max_num DO SELECT i AS number; SET i = i + 1; END WHILE; END // DELIMITER ;
六、完整示例:员工加薪
假设我们需要给指定部门的员工统一加薪,并返回加薪后的平均工资。
DELIMITER // CREATE PROCEDURE RaiseSalary( IN dept_name VARCHAR(50), IN percent DECIMAL(5,2), OUT new_avg DECIMAL(10,2) ) BEGIN -- 更新员工工资 UPDATE employees SET salary = salary * (1 + percent/100) WHERE department = dept_name; -- 计算新的平均工资 SELECT AVG(salary) INTO new_avg FROM employees WHERE department = dept_name; END // DELIMITER ;
调用:
CALL RaiseSalary('技术部', 10, @avg);
SELECT @avg;七、注意事项
分隔符问题:创建存储过程时务必使用 DELIMITER 临时更改结束符,创建完后再改回 ;。
权限:创建存储过程需要 CREATE ROUTINE 权限,执行需要 EXECUTE 权限。
调试困难:存储过程的调试相对复杂,建议先测试好 SQL 语句再封装。
不要过度使用:存储过程会将业务逻辑分散在数据库和应用层,可能影响代码的可移植性和维护性。适当使用即可。
MySQL 版本差异:不同 MySQL 版本对存储过程的支持可能略有差异,建议使用较新版本(5.5+ 基本稳定)。
八、小结
存储过程 是数据库中的可编程模块,封装了 SQL 语句和逻辑。
使用 CREATE PROCEDURE 创建,CALL 调用,DROP PROCEDURE 删除。
支持 IN、OUT、INOUT 参数,以及局部变量和流程控制。
可以提高性能、复用性和安全性,但也需注意维护成本。

发表评论
所有评论