觸發器是針對表級 DML(INSERT/UPDATE/DELETE)自動執行的存儲程序,常用於數據遷移同步、審計追蹤、衍生列計算、跨表同步。本文通過 SQL Server→MySQL 遷移案例、審計日誌、刪除備份三大場景,講解觸發器編寫技巧與常見陷阱。
ALTER TRIGGER [trg_risks] ON dbo.projectrisk FOR INSERT, UPDATE AS
BEGIN
UPDATE projectrisk SET classification =
CASE WHEN calc>=9 THEN 3 WHEN calc<9 AND calc>=4 THEN 2 WHEN calc<4 THEN 1 END
FROM (SELECT inserted.id, inserted.possibility*inserted.severity AS calc FROM inserted) T1
WHERE projectrisk.id = T1.id
END
inserted 表,使用 NEW 引用新行BEFORE 觸發器可直接修改 NEW.column,避免遞歸更新CREATE TRIGGER trg_risks_insert AFTER INSERT ON projectrisk FOR EACH ROW UPDATE projectrisk SET classification = ... WHERE id = NEW.id; -- 觸發 UPDATE 觸發器 → 無限遞歸
DELIMITER &&
CREATE TRIGGER trg_risks_insert BEFORE INSERT ON projectrisk FOR EACH ROW
BEGIN
SET NEW.classification = CASE
WHEN NEW.possibility * NEW.severity >= 9 THEN 3
WHEN NEW.possibility * NEW.severity >= 4 THEN 2
ELSE 1
END;
END &&
CREATE TRIGGER trg_risks_update BEFORE UPDATE ON projectrisk FOR EACH ROW
BEGIN
SET NEW.classification = CASE
WHEN NEW.possibility * NEW.severity >= 9 THEN 3
WHEN NEW.possibility * NEW.severity >= 4 THEN 2
ELSE 1
END;
END &&
DELIMITER ;
核心原則: 需修改同表數據時,必須用 BEFORE 觸發器 + SET NEW.col,切勿用 AFTER 觸發器再 UPDATE 同表。
DELIMITER $$
CREATE TRIGGER InsertOPM_Alarm_trigger BEFORE INSERT ON OPM_Alarm FOR EACH ROW
BEGIN
INSERT INTO OPM_Alarm_copy (
AlarmId, AlarmCode, AlarmTypeId, AlarmLevelId, AlarmObjectCode,
AlarmStatus, AlarmHandleUser, AlarmHandleTime, ADDTIME,
ParkUserId, BerthCode, BargainOrderCode, BerthStartTime
) VALUES (
NEW.AlarmId, NEW.AlarmCode, NEW.AlarmTypeId, NEW.AlarmLevelId, NEW.AlarmObjectCode,
NEW.AlarmStatus, NEW.AlarmHandleUser, NEW.AlarmHandleTime, NEW.ADDTIME,
NEW.ParkUserId, NEW.BerthCode, NEW.BargainOrderCode, NEW.BerthStartTime
);
END;
$$
DELIMITER ;
DELIMITER $$ CREATE TRIGGER BackupOPM_Alarm_trigger BEFORE DELETE ON OPM_Alarm FOR EACH ROW BEGIN INSERT INTO OPM_Alarm_copy (AlarmId, AlarmCode, ..., BerthStartTime) VALUES (OLD.AlarmId, OLD.AlarmCode, ..., OLD.BerthStartTime); END; $$ DELIMITER ;
DELIMITER $$
CREATE TRIGGER SYS_OPM_trigger AFTER DELETE ON OPM_Alarm FOR EACH ROW
BEGIN
DECLARE str VARCHAR(40000);
SET str = CONCAT(
OLD.AlarmId, '@', OLD.AlarmCode, '@', OLD.AlarmTypeId, '@', OLD.AlarmLevelId, '@',
OLD.AlarmObjectCode, '@', OLD.AlarmStatus, '@', OLD.AlarmHandleUser, '@', OLD.AlarmHandleTime, '@',
OLD.AddTime, '@', OLD.ParkUserId, '@', OLD.BerthCode, '@', OLD.BargainOrderCode, '@', OLD.BerthStartTime
);
INSERT INTO OPM_AlarmAction_log (UserName, Client_IP, Delete_before_key, Delete_Date)
VALUES (
SUBSTRING_INDEX(USER(), '@', 1), -- 當前用戶名
SUBSTRING_INDEX(USER(), '@', -1), -- 客戶端 IP
str, -- 序列化完整舊行
NOW()
);
END;
$$
DELIMITER ;
| 操作 | 命令 |
|---|---|
| 查看所有觸發器 | SHOW TRIGGERS; |
| 查看指定庫觸發器 | SHOW TRIGGERS FROM db_name; |
| 查看創建語句 | SHOW CREATE TRIGGER trigger_name; |
| 刪除觸發器 | DROP TRIGGER [IF EXISTS] trigger_name; |
| 元數據查詢 | SELECT * FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_SCHEMA='db' AND TRIGGER_NAME='name'\G |
mysqldump --triggers 導出觸發器,導入時需確保 DEFINER 賬號存在或用 --skip-definerFOLLOWS/PRECEDES 控制順序)