MySQL 存儲過程與自定義函數是將業務邏輯下沉到數據庫層的利器,能減少網絡交互、提升執行效率、封裝復雜邏輯。本文系統講解:函數與過程的語法差異、參數模式(IN/OUT/INOUT)、復合結構體、調用方式、權限控制,並對比兩者適用場景,基於 MySQL 8.0 語法演示。
RETURNS 聲明,函數體必須包含 RETURN 語句BEGIN ... END 中DETERMINISTIC 或 NOT DETERMINISTICDELIMITER //
CREATE FUNCTION f_chinese_now()
RETURNS VARCHAR(30)
DETERMINISTIC
BEGIN
RETURN DATE_FORMAT(NOW(), '%Y年%m月%d日 %H點:%i分:%s秒');
END //
DELIMITER ;
-- 調用
SELECT f_chinese_now();
CREATE FUNCTION f_add_float(num1 SMALLINT UNSIGNED, num2 SMALLINT UNSIGNED) RETURNS DECIMAL(10,2) UNSIGNED DETERMINISTIC RETURN num1 + num2; SELECT f_add_float(32, 33); -- 65.00
演示 DELIMITER 臨時修改語句結束符,避免函數體內分號衝突。
DELIMITER //
CREATE FUNCTION f_add_user(p_username VARCHAR(20))
RETURNS INT UNSIGNED
NOT DETERMINISTIC
BEGIN
INSERT INTO `test` (`username`) VALUES (p_username);
RETURN LAST_INSERT_ID();
END //
DELIMITER ;
SELECT f_add_user('Rose'); -- 返回新記錄 ID
SHOW FUNCTION STATUS WHERE Db = 'test'; -- 查看 DROP FUNCTION IF EXISTS f_add_user; -- 刪除
| 特性 | 函數 | 存儲過程 |
|---|---|---|
| 返回值 | 單一值(必須) | 可通過 OUT/INOUT 參數返回多值 |
| 調用方式 | SELECT func() / 表達式中 | CALL proc() / CALL proc |
| 事務控制 | 不支持 | 支持 START TRANSACTION/COMMIT/ROLLBACK |
| 表操作 | 受限(不建議增刪改) | 完全支持 DML/DDL |
| 參數模式 | 僅 IN | IN / OUT / INOUT |
CREATE PROCEDURE sp_version() SELECT VERSION(); CALL sp_version(); -- 或 CALL sp_version
DELIMITER //
CREATE PROCEDURE sp_del_user(IN p_id INT UNSIGNED)
BEGIN
DELETE FROM `test` WHERE `id` = p_id;
END //
DELIMITER ;
CALL sp_del_user(3);
⚠ 避坑指南: 參數名勿與表字段名重名(如 id),否則 WHERE id = id 恆真導致全表刪除。建議參數加前綴 p_。
DELIMITER //
CREATE PROCEDURE sp_del_count(IN p_id INT UNSIGNED, OUT p_remain INT UNSIGNED)
BEGIN
DELETE FROM `test` WHERE `id` = p_id;
SELECT COUNT(*) INTO p_remain FROM `test`;
END //
DELIMITER ;
CALL sp_del_count(3, @remain);
SELECT @remain; -- 用戶變量以 @ 開頭,會話級作用域
DELIMITER //
CREATE PROCEDURE sp_del_age(IN p_age SMALLINT UNSIGNED,
OUT p_deleted SMALLINT UNSIGNED,
OUT p_remain SMALLINT UNSIGNED)
BEGIN
DELETE FROM `test` WHERE `age` = p_age;
SELECT ROW_COUNT() INTO p_deleted;
SELECT COUNT(*) INTO p_remain FROM `test`;
END //
DELIMITER ;
CALL sp_del_age(20, @del, @rem);
SELECT @del, @rem;
存儲過程支持 IF...ELSEIF...ELSE...END IF、CASE、WHILE、REPEAT、LOOP、ITERATE、LEAVE 等,可實現複雜業務邏輯。
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SELECT 'ERROR' AS result;
END;
CREATE ROUTINE 權限,調用者需 EXECUTE 權限DEFINER / INVOKER 指定執行上下文,防止權限提升SHOW PROCEDURE STATUS、EXPLAIN 內部查詢