核心差異速查表
| 維度 | 存儲過程 (PROCEDURE) | 函數 (FUNCTION) |
| 定義關鍵字 | CREATE PROCEDURE | CREATE FUNCTION |
| 調用方式 | CALL proc_name(...) 獨立語句 | SELECT func_name(...) 嵌入 SQL 表達式 |
| 返回值 | 無返回值,通過 OUT/INOUT 參數回傳多個值 | 必須 返回單一值(標量或表) |
| 參數模式 | IN、OUT、INOUT | 僅 IN |
| 事務控制 | 可显式 COMMIT/ROLLBACK、啟動事務 | 不可包含事務控制語句 |
| 修改數據 | 可執行 INSERT/UPDATE/DELETE/DDL | 不可修改全局數據庫狀態(不可寫表) |
| 非確定性 | 可使用 RAND()、UUID() 等 | 默認 DETERMINISTIC,若需非確定性須顯式聲明 NOT DETERMINISTIC |
| 權限 | CREATE ROUTINE、EXECUTE | CREATE ROUTINE、EXECUTE |
| 在 SQL 中使用 | 不可直接用於 SELECT/WHERE/FROM | 可用於 SELECT 列、WHERE 條件、FROM 子查詢(返回表) |
典型應用場景
存儲過程
- 複雜業務邏輯封裝:批量轉賬、報表生成、數據清洗、定時任務核心邏輯。
- 需事務控制、多步寫入、動態 SQL 構建。
- 減少應用與資料庫交互往返(網絡延遲)。
函數
- 可復用的計算/轉換邏輯:金額格式化、狀態碼轉換、自定義聚合、字符串處理。
- 需在
SELECT 列表、WHERE、JOIN ON 中直接調用。
- 返回表的
TABLE FUNCTION (MySQL 8.0+) 可用於 FROM func()。
代碼對比
-- 存儲過程:修改數據、多 OUT 參數
CREATE PROCEDURE transfer(IN from_id INT, IN to_id INT, IN amount DECIMAL(10,2),
OUT success BOOL, OUT msg VARCHAR(100))
BEGIN
DECLARE bal DECIMAL(10,2);
SELECT balance INTO bal FROM account WHERE id = from_id FOR UPDATE;
IF bal >= amount THEN
UPDATE account SET balance = balance - amount WHERE id = from_id;
UPDATE account SET balance = balance + amount WHERE id = to_id;
SET success = TRUE; SET msg = 'OK';
ELSE
SET success = FALSE; SET msg = 'Insufficient balance';
END IF;
END;
-- 函數:純計算、單返回值
CREATE FUNCTION format_money(amt DECIMAL(10,2)) RETURNS VARCHAR(20)
DETERMINISTIC
RETURN CONCAT('¥', FORMAT(amt, 2));
-- 調用
CALL transfer(1,2,100,@s,@m);
SELECT format_money(balance) FROM account;
選型建議
- 需寫數據、事務、多返回值 → 存儲過程。
- 純計算、需嵌入 SQL 表達式、單返回值 → 函數。
- 現代架構傾向:業務邏輯上移到應用層,資料庫僅做數據存取與約束,存儲過程/函數僅用於極簡、高頻、跨應用復用的邏輯。