MySQL 5.0+ 支援四類伺服器端存儲對象:
| 類型 | 關鍵字 | 觸發方式 | 返回值 | 適用版本 |
|---|---|---|---|---|
| 存儲函數 | FUNCTION | SQL 表達式中呼叫 | 單一標量值 | 5.0.0+ |
| 存儲過程 | PROCEDURE | CALL 語句呼叫 | 無(透過 OUT 參數/結果集) | 5.0.0+ |
| 觸發器 | TRIGGER | 表 DML 操作自動觸發 | 無 | 5.0.2+ |
| 事件 | EVENT | 排程時間自動執行 | 無 | 5.1.6+ |
DEFINER/INVOKER 權限模型,實現資料存取最小權限存儲程序主體為 複合語句:BEGIN ... END 區塊包含多條 SQL,語句間以 ; 分隔。但 ; 也是 mysql 客戶端預設分隔符,定義時必須暫時變更:
DELIMITER $$
CREATE PROCEDURE demo()
BEGIN
DECLARE v INT DEFAULT 0;
WHILE v < 5 DO
SELECT v;
SET v = v + 1;
END WHILE;
END$$
DELIMITER ;
原則:主體內含 ; 時,定義前必須 DELIMITER 新符號,結束後恢復 DELIMITER ;。
CREATE FUNCTION count_born_in_year(p_year INT)
RETURNS INT
DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE cnt INT;
SELECT COUNT(*) INTO cnt FROM president WHERE YEAR(birth) = p_year;
RETURN cnt;
END
RETURNS:宣告返回型別DETERMINISTIC:相同輸入必得相同輸出(二進制日誌安全需要)READS SQL DATA:聲明只讀資料(或 NO SQL/MODIFIES SQL DATA)RETURNSELECT count_born_in_year(1950); -- 可用於表達式
CREATE PROCEDURE show_born_in_year(p_year INT)
BEGIN
SELECT name, birth FROM president WHERE YEAR(birth) = p_year;
END
RETURNS、無 RETURN 值OUT/INOUT 參數回傳多值CALL show_born_in_year(1950);
| 模式 | 說明 | 函數/過程 |
|---|---|---|
| IN | 呼叫端傳入,過程內修改不回傳 | 函數預設皆為 IN;過程預設 IN |
| OUT | 過程內賦值,返回後呼叫端可讀 | 僅過程支援 |
| INOUT | 呼叫端傳入,過程修改後返回 | 僅過程支援 |
CREATE PROCEDURE count_by_sex(OUT p_male INT, OUT p_female INT)
BEGIN
SELECT COUNT(*) INTO p_male FROM student WHERE sex='M';
SELECT COUNT(*) INTO p_female FROM student WHERE sex='F';
END
CALL count_by_sex(@m, @f);
SELECT @m, @f;
CREATE ROUTINE 權限EXECUTE、ALTER ROUTINEautomatic_sp_privileges=0 可關閉自動授權DETERMINISTIC/NO SQL/READS SQL DATA 其中之一,否則需 SUPER 權限或開啟 log_bin_trust_function_creators=1CREATE TRIGGER trg_bi_user
BEFORE INSERT ON `user`
FOR EACH ROW
BEGIN
IF NEW.email NOT LIKE '%@%' THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Invalid email';
END IF;
SET NEW.created_at = NOW();
END
BEFORE/AFTERINSERT/UPDATE/DELETEFOR EACH ROW(MySQL 僅支援行級)NEW.col、OLD.colCREATE EVENT ev_cleanup_logs
ON SCHEDULE EVERY 1 DAY
STARTS '2024-01-01 02:00:00'
DO
DELETE FROM logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
event_scheduler=ONDECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @msg = MESSAGE_TEXT;
INSERT INTO error_log VALUES (@sqlstate, @msg, NOW());
END;
fn_ 函數、sp_ 過程、trg_ 觸發器、ev_ 事件SHOW PROFILE、performance_schema 分析執行耗時MySQL 存儲程序提供完整的程式化能力(變數、流控、錯誤處理、權限模型),核心價值在於邏輯下沉、網路減載、安全封裝。掌握 DELIMITER、參數模式、權限與二進制日誌限制,是正確使用的關鍵。現代架構下,建議將業務核心邏輯留在應用層,存儲程序專注於資料層面的批次、維護、審計、同步等場景。