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) AS T1
WHERE projectrisk.id = T1.id
END
inserted 表,用 NEW 訪問新行CREATE TRIGGER trg_risks_ai AFTER INSERT ON projectrisk FOR EACH ROW UPDATE projectrisk SET classification = ... WHERE id = NEW.id; -- 觸發 AFTER UPDATE → 死循環
DELIMITER //
CREATE TRIGGER trg_risks_bi
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_bu
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** 修改 NEW;關聯表同步、日誌記錄、異步通知 → **AFTER** 讀取 NEW。
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;
-- 刪除前備份原數據
CREATE TRIGGER BackupOPM_Alarm_trigger
BEFORE DELETE ON OPM_Alarm
FOR EACH ROW
BEGIN
INSERT INTO OPM_Alarm_copy (...) VALUES (OLD.AlarmId, OLD.AlarmCode, ...);
END;
-- 審計日誌:記錄誰、從哪裡、刪除了什麼、何時
CREATE TRIGGER AuditOPM_Alarm_trigger
AFTER DELETE ON OPM_Alarm
FOR EACH ROW
BEGIN
DECLARE log_str VARCHAR(4000);
SET log_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
log_str,
NOW()
);
END;
+----------------+ Trigger (AFTER) +------------------+
| 核心業務庫 | --------------------> | 同步/審計庫 |
| (InnoDB) | INSERT/UPDATE/DELETE | (歸檔、報表、ES) |
+----------------+ +------------------+
| ^
| Binlog (Canal/Maxwell) | Trigger 寫入
v |
+----------------+ +------------------+
| 異構目標庫 | <------------------- | 消費端解析寫入 |
| (ClickHouse, | Binlog 事件流 | (異步、高吞吐) |
| Elasticsearch)| +------------------+
+----------------+
INSERT ... VALUES (...),(...),(...) 會逐行觸發,大批量導入時考慮暫時禁用觸發器DROP TRIGGER / 重建,或用會話變量標誌 @DISABLE_TRIGGER 在觸發器首行判斷SHOW GLOBAL STATUS LIKE 'Trigger%';(需 8.0+)觀察觸發次數、耗時| 場景 | 觸發器類型 | 關鍵技巧 |
|---|---|---|
| 衍生列計算 | BEFORE INSERT/UPDATE | 直接 SET NEW.col = ... |
| 同表業務約束 | BEFORE | SIGNAL SQLSTATE 拋錯阻止 |
| 關聯表同步 | AFTER | 讀取 NEW 寫入目標表 |
| 審計日誌 | AFTER | CONCAT 關鍵字段 + USER()/NOW() |
| 刪除歸檔 | BEFORE DELETE | INSERT ... VALUES (OLD.*) |
觸發器雖強大,但**隱式邏輯難排查**、**增加寫入延遲**、**備份恢復需同步觸發器定義**。架構選型時優先考慮**應用層顯式寫入**或**Binlog 異步同步**,觸發器作為輔助手段用於強一致性要求極高的核心表。