存儲過程是預編譯 SQL 語句集,存儲於數據庫服務端,通過名稱調用。相較於客戶端發送單條 SQL,它能封裝業務邏輯、減少網絡交互、提升執行效率,是數據庫端編程的核心技能。
EXECUTE 權限,間接實現數據訪問控制。CREATE PROCEDURE proc_name ([IN|OUT|INOUT] param_name type, ...)
[characteristic ...]
routine_body
IN:輸入參數,調用時必須提供,內部修改不返回。OUT:輸出參數,內部賦值並返回調用者。INOUT:雙向參數,調用時傳入,內部可修改並返回。DELIMITER $$
CREATE PROCEDURE proc_in(IN p_in INT)
BEGIN
SELECT p_in; -- 輸出 1
SET p_in = 2;
SELECT p_in; -- 輸出 2
END$$
DELIMITER ;
SET @p_in = 1;
CALL proc_in(@p_in);
SELECT @p_in; -- 仍為 1,原變量未受影響
DELIMITER $$
CREATE PROCEDURE proc_out(OUT p_out INT)
BEGIN
SELECT p_out; -- 輸出 NULL
SET p_out = 2;
SELECT p_out; -- 輸出 2
END$$
DELIMITER ;
SET @p_out = 1;
CALL proc_out(@p_out);
SELECT @p_out; -- 變為 2,外部變量被修改
結合上述特性,調用前賦值,調用後獲取新值,適用於累加、狀態流轉等場景。
-- IF-THEN-ELSE
IF condition THEN ... ELSEIF ... ELSE ... END IF;
-- CASE 語句
CASE var
WHEN 0 THEN INSERT INTO t VALUES(17);
WHEN 1 THEN INSERT INTO t VALUES(18);
ELSE INSERT INTO t VALUES(19);
END CASE;
LEAVE label 跳出。continue)。-- WHILE 示例
WHILE v < 5 DO
INSERT INTO t VALUES(v);
SET v = v + 1;
END WHILE;
-- REPEAT 示例
REPEAT
INSERT INTO t VALUES(v);
SET v = v + 1;
UNTIL v >= 5
END REPEAT;
-- LOOP + LEAVE + ITERATE
loop_label: LOOP
IF v = 3 THEN
SET v = v + 1;
ITERATE loop_label; -- 跳過 insert
END IF;
INSERT INTO t VALUES(v);
SET v = v + 1;
IF v >= 5 THEN LEAVE loop_label; END IF;
END LOOP;
| 操作 | 語法 |
|---|---|
| 調用 | CALL proc_name([args...]); |
| 查看列表 | SHOW PROCEDURE STATUS WHERE db='db_name'; 或查 information_schema.routines |
| 查看定義 | SHOW CREATE PROCEDURE db_name.proc_name; |
| 修改 | ALTER PROCEDURE proc_name [characteristic ...]; |
| 刪除 | DROP PROCEDURE [IF EXISTS] proc_name; |
DECLARE 定義局部變量,避免污染會話變量(@var)。ANALYZE PROCEDURE 更新統計信息(MySQL 8.0+ 支持)。