測試資料表結構
-- 分數表
CREATE TABLE sc (
ScId INT NOT NULL PRIMARY KEY,
SNo INT NOT NULL,
CNo INT NOT NULL,
Score INT DEFAULT NULL
);
-- 異動記錄表
CREATE TABLE score_record (
SrId INT NOT NULL PRIMARY KEY,
SNo INT NOT NULL,
CNo INT NOT NULL,
OldScore INT NOT NULL,
NewScore INT NOT NULL,
UpdateTime DATETIME NOT NULL
);
MySQL 觸發器寫法
DROP TRIGGER IF EXISTS `trigger_sr`;
DELIMITER //
CREATE TRIGGER `trigger_sr` AFTER UPDATE ON `sc`
FOR EACH ROW
BEGIN
INSERT INTO score_record (SNo, CNo, OldScore, NewScore, UpdateTime)
VALUES (NEW.SNo, NEW.CNo, OLD.Score, NEW.Score, NOW());
END//
DELIMITER ;
SQL Server 觸發器寫法
CREATE TRIGGER trigger_sr ON sc
FOR UPDATE
AS
BEGIN
DECLARE @SNo INT, @CNo INT, @OldScore INT, @NewScore INT;
SELECT @SNo = SNo, @CNo = CNo, @OldScore = Score FROM deleted;
SELECT @NewScore = Score FROM inserted;
INSERT INTO score_record (SNo, CNo, OldScore, NewScore, UpdateTime)
VALUES (@SNo, @CNo, @OldScore, @NewScore, GETDATE());
END;
核心差異對照
| 特性 | MySQL | SQL Server |
| 觸發時機關鍵字 | BEFORE / AFTER | FOR / AFTER / INSTEAD OF |
| 行級觸發 | FOR EACH ROW (預設行級) | 陳述式級,需自行處理 inserted/deleted 虛擬表 |
| 新/舊值引用 | NEW.col / OLD.col | inserted.col / deleted.col |
| 分隔符處理 | 需 DELIMITER 變更 | 無需特殊分隔符 |
| 變數宣告 | DECLARE var TYPE; 在 BEGIN 內 | DECLARE @var TYPE; 在 BEGIN 內 |
| 取得當前時間 | NOW() | GETDATE() |
延伸提醒
- MySQL 觸發器不支援交易控制(
COMMIT/ROLLBACK),SQL Server 可在觸發器內隱含交易。
- 複雜邏輯建議移至預存程序,觸發器保持輕量。
- 遷移時注意資料類型對應(如
DATETIME 精度差異)。