一組預編譯的 SQL 語句集合,駐留在數據庫服務器端,支持參數輸入/輸出、變量聲明、條件判斷、循環等過程化邏輯,類比 Java 方法。主動調用(CALL),區別於觸發器的被動觸發。
IN(輸入)、OUT(輸出)、INOUT(雙向)DECLARE var TYPE [DEFAULT val]IF/ELSEIF/ELSE、CASE、WHILE/REPEAT/LOOP、ITERATE/LEAVEDELIMITER ;;
CREATE PROCEDURE proc_adder (IN a INT, IN b INT, OUT sum INT)
BEGIN
DECLARE c INT DEFAULT 0;
IF a IS NULL THEN SET a = 0; END IF;
IF b IS NULL THEN SET b = 0; END IF;
SET sum = a + b;
END;;
DELIMITER ;
-- 調用驗證
SET @b = 5;
CALL proc_adder(2, @b, @s);
SELECT @s AS sum; -- 7
關鍵點:DELIMITER ;; 臨時修改語句結束符,避免過程體內分號被誤判為結束。
CREATE PROCEDURE proc_if (IN type INT)
BEGIN
DECLARE c VARCHAR(500);
IF type = 0 THEN SET c = 'param is 0';
ELSEIF type = 1 THEN SET c = 'param is 1';
ELSE SET c = 'param is others';
END IF;
SELECT c;
END;
CREATE PROCEDURE proc_case (IN type INT)
BEGIN
DECLARE c VARCHAR(500);
CASE type
WHEN 0 THEN SET c = 'param is 0';
WHEN 1 THEN SET c = 'param is 1';
ELSE SET c = 'param is others';
END CASE;
SELECT c;
END;
CREATE PROCEDURE proc_while (IN n INT)
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE s INT DEFAULT 0;
WHILE i <= n DO
SET s = s + i;
SET i = i + 1;
END WHILE;
SELECT s; -- 返回 0+1+...+n
END;
DECLARE cur CURSOR FOR SELECT ... 逐行處理結果集DECLARE CONTINUE/EXIT HANDLER FOR SQLSTATE '23000' ... 捕獲異常PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;| 缺點 | 影響 | 建議 |
|---|---|---|
| 語法差異大 | 遷移極難(MySQL→PostgreSQL/Oracle 需全改寫) | 核心業務邏輯留在應用層,僅將**高頻、簡單、性能敏感**的邏輯下沉 |
| 難以版本控制/代碼評審 | 維護混亂,易成「黑盒」 | 嚴格命名規範、註釋、單獨 SQL 文件管理、納入 CI/CD |
| 調試困難 | 無斷點、變量觀察 | 用 SELECT ... INTO @var 打印中間值,或引入 sys.diagnostics 工具 |
| 鎖持有時間長 | 長事務阻塞並發 | 控制過程體執行時間 < 100ms,避免複雜計算 |
proc__ (如 proc_order_create)OUT 參數初始化SELECT),改用 OUT 參數或臨時表存儲過程是「雙刃劍」:用對是性能利器,用錯是維護噩夢。**克制下沉,精準施策**。