DELIMITER // CREATE PROCEDURE GetUserOrders(IN userId INT) BEGIN SELECT * FROM orders WHERE user_id = userId; END // DELIMITER ; CALL GetUserOrders(1);
存储过程基础
存储过程是一组预编译的SQL语句集合,可以作为一个单元而被调用。MariaDB/MySQL中,存储过程的好处是减少客户端和服务器之间的通信量,提高安全性,因为不需要动态SQL,并且可以重用代码。创建存储过程的基本语法是:CREATE PROCEDURE 过程名(参数列表) BEGIN ... END;
函数实战示例
CREATE FUNCTION CalculateDiscount(price DECIMAL(10,2), discount_rate INT) RETURNS DECIMAL(10,2) READS SQL DATA DETERMINISTIC BEGIN DECLARE discount DECIMAL(10,2); SET discount = price * (discount_rate / 100); RETURN price - discount; END;
变量与条件控制
在存储过程中可以使用DECLARE声明变量,如DECLARE counter INT DEFAULT 0; 条件语句IF ... THEN ... ELSEIF ... ELSE ... END IF; 循环有WHILE、REPEAT、LOOP三种形式。例如:WHILE counter < 10 DO SET counter = counter + 1; END WHILE;
游标使用
游标用于逐行处理查询结果集。DECLARE cur CURSOR FOR SELECT * FROM table; OPEN cur; FETCH cur INTO var1, var2; CLOSE cur; 这在批量处理数据时非常有用,避免了低效的手工循环。
错误处理
使用DECLARE ... HANDLER FOR SQLEXCEPTION BEGIN ... END; 来捕获异常,确保过程的鲁棒性。例如,HANDLER FOR SQLEXCEPTION SET @error = 1;
存储过程优化
使用EXPLAIN分析过程内部查询,添加合适的索引,避免在循环中使用SELECT INTO。参数使用IN、OUT、INOUT类型。过程结束后用SELECT输出结果,便于客户端获取。
实际业务案例
月度报表生成过程:统计每个用户的订单总额,更新用户积分。CREATE PROCEDURE MonthlyReport() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE user_id INT; DECLARE total DECIMAL(10,2); DECLARE cur CURSOR FOR SELECT id, SUM(amount) FROM orders GROUP BY id; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur; read_loop: LOOP FETCH cur INTO user_id, total; IF done THEN LEAVE read_loop; END IF; UPDATE users SET points = points + total WHERE id = user_id; END LOOP; CLOSE cur; END;
FAQ
Q: 存储过程和函数的区别是什么?
A: 存储过程可以有多个SQL语句,返回多行结果,主要用于批量操作;函数通常返回单一值,用于计算。
Q: 如何调试存储过程?
A: 使用SELECT语句输出中间变量值,或者启用general_log查看执行日志。
Q: 存储过程能提高性能吗?
A: 是的,因为预编译,减少网络传输,适合复杂业务逻辑。
Q: 如何删除存储过程?
A: DROP PROCEDURE IF EXISTS 过程名;