觸發器在 **事務內部** 執行,與觸發語句共享事務上下文。若觸發器回滾,原語句也回滾。因此:
INSERTED / DELETED 虛擬表獲取變更行集(集合思維,勿逐行游標)。
CREATE TRIGGER trg_A_Insert_Sync_B
ON TableA
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO TableB (Col1, Col2, Col3)
SELECT Col1, Col2, Col3
FROM INSERTED;
END;
GO
CREATE TRIGGER trg_A_Delete_Sync_B
ON TableA
AFTER DELETE
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM TableB
WHERE PK_Col IN (SELECT PK_Col FROM DELETED);
END;
GO
CREATE TRIGGER trg_A_Update_Sync_B
ON TableA
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE B
SET B.Col1 = I.Col1,
B.Col2 = I.Col2,
B.Col3 = I.Col3
FROM TableB B
INNER JOIN INSERTED I ON B.PK_Col = I.PK_Col;
END;
GO
CREATE TRIGGER trg_A_Sync_B
ON TableA
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON;
-- 同步新增/更新(MERGE UPSERT)
MERGE TableB AS T
USING (SELECT * FROM INSERTED) AS S
ON T.PK_Col = S.PK_Col
WHEN MATCHED THEN UPDATE SET T.Col1=S.Col1, T.Col2=S.Col2, T.Col3=S.Col3
WHEN NOT MATCHED BY TARGET THEN INSERT (PK_Col,Col1,Col2,Col3) VALUES (S.PK_Col,S.Col1,S.Col2,S.Col3);
-- 同步刪除
DELETE FROM TableB
WHERE PK_Col IN (SELECT PK_Col FROM DELETED)
AND PK_Col NOT IN (SELECT PK_Col FROM INSERTED); -- 排除 UPDATE 產生的 DELETED 行
END;
GO
| 場景 | 建議 |
|---|---|
| 高頻寫入、大批次 | 觸發器會嚴重拖慢寫入延遲,改用 **CDC (Change Data Capture)** + 異步消費 |
| 跨庫/跨服務器同步 | 觸發器不支援分布式事務可靠性,改用 **Service Broker** / **Replication** / **Kafka + Debezium** |
| 審計/歷史記錄 | 觸發器寫歷史表可行,但建議 **Temporal Table (SQL 2016+)** 自動維護歷史 |
| 簡單低頻業務 | 觸發器可接受,代碼清晰、部署簡單 |
觸發器是「數據庫內部的事件總線」,用對是利器,濫用是毒藥。掌握 INSERTED/DELETED 集合操作、MERGE 合並邏輯、事務邊界共享特性,並在架構層面評估 CDC/Service Broker/Temporal Table 等現代替代方案,才是成熟 DBA/開發的選擇。