inserted(新版本資料)、deleted(舊版本資料),結構與觸發表同步,存在 tempdb,觸發結束自動釋放。CREATE TRIGGER schema.trigger_name
ON schema.table_or_view
[WITH ENCRYPTION]
{ FOR | AFTER | INSTEAD OF } [INSERT] [,] [UPDATE] [,] [DELETE]
[NOT FOR REPLICATION]
AS
BEGIN
SET NOCOUNT ON;
-- T-SQL 邏輯
END;
GO
ALTER TRIGGER schema.trigger_name
ON schema.table_or_view
[WITH ENCRYPTION]
{ FOR | AFTER | INSTEAD OF } [INSERT] [,] [UPDATE] [,] [DELETE]
[NOT FOR REPLICATION]
AS
BEGIN
SET NOCOUNT ON;
-- 修改後邏輯
END;
GO
DROP TRIGGER [schema.]trigger_name;
GO
SELECT name, object_id, parent_class_desc, create_date, modify_date, is_disabled
FROM sys.triggers
WHERE parent_class = 1; -- 1 = 表/檢視表
EXEC sp_helptext 'trigger_name';
-- 或
SELECT OBJECT_DEFINITION(OBJECT_ID('trigger_name'));
SELECT t.name, te.type_desc
FROM sys.triggers t
JOIN sys.trigger_events te ON te.object_id = t.object_id
WHERE t.name = 'trigger_name';
DISABLE TRIGGER trigger_name ON schema.table; -- 停用
ENABLE TRIGGER trigger_name ON schema.table; -- 啟用
-- 全資料庫
DISABLE TRIGGER ALL ON DATABASE;
ENABLE TRIGGER ALL ON DATABASE;
CREATE TRIGGER trg_Order_Insert_CheckStatus
ON Orders
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS (
SELECT 1
FROM inserted i
JOIN Goods g ON g.Name = i.GoodsName
WHERE g.Status = 1 -- 1 = 整理中
)
BEGIN
RAISERROR('該貨品正在整理中,無法下單。', 16, 1);
ROLLBACK TRANSACTION;
END
END;
GO
CREATE TRIGGER trg_Order_Insert_DeductStock
ON Orders
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE g
SET g.Storage = g.Storage - i.Quantity
FROM Goods g
JOIN inserted i ON g.Name = i.GoodsName;
END;
GO
CREATE TRIGGER trg_Goods_Delete_Cascade
ON Goods
AFTER DELETE
AS
BEGIN
SET NOCOUNT ON;
DELETE o
FROM Orders o
JOIN deleted d ON o.GoodsName = d.Name;
END;
GO
CREATE TRIGGER trg_Order_Update_ProtectDate
ON Orders
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE(OrderDate)
BEGIN
RAISERROR('訂單日期禁止修改。', 16, 1);
ROLLBACK TRANSACTION;
END
END;
GO
CREATE TRIGGER trg_Order_Insert_ValidateGoods
ON Orders
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS (
SELECT 1
FROM inserted i
LEFT JOIN Goods g ON g.Name = i.GoodsName
WHERE g.Name IS NULL
)
BEGIN
RAISERROR('下單貨品不存在於主檔。', 16, 1);
ROLLBACK TRANSACTION;
END
END;
GO
ALTER TRIGGER trg_Order_Insert_SyncExternal
ON Orders
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO ExternalOrder (Id, GoodName, Quantity)
SELECT Id, GoodName, Quantity FROM inserted;
END;
GO
| 主題 | 關鍵點 |
|---|---|
| 遞迴觸發 | 觸發器修改同表 → 再次觸發。sp_configure 'nested triggers', 0 關閉;或用 TRIGGER_NESTLEVEL() 判斷層級跳出。 |
| TRUNCATE TABLE | 不觸發 DELETE 觸發器,若需攔截請改用權限控制或 CDC。 |
| 禁止語句 | 觸發器內不可執行:ALTER/CREATE/DROP DATABASE, RESTORE, RECONFIGURE, DISK 等。 |
| 效能 | 避免游標、發送郵件、呼叫外部 API;大量資料改用 MERGE/集合運算;必要時 SET NOCOUNT ON。 |
| 權限 | 建立觸發器需 ALTER 表權限;執行時以觸發器擁有者權限(非呼叫者)。 |
| 加密 | WITH ENCRYPTION 可隱藏定義,但可被反編譯,非絕對安全。 |
PRINT 'DEBUG: ...' 或寫入 DebugLog 表。EXEC sp_trace_setevent / Extended Events 捕獲)。ROLLBACK,配合 tSQLt 框架自動化。掌握觸發器全生命週期管理與範例庫,即能在資料庫層落實資料完整性、審計追蹤、跨表同步等橫切關注點,同時避開常見效能與維護陷阱。