在 SQL Server 觸發器中,inserted 和 deleted 是兩張特殊的**虛擬表**(概念表),僅存在於觸發器執行期間,分別保存 DML 操作前後的資料快照。它們不佔用實體儲存空間,讀取效能極高。
| 觸發動作 | inserted 表 | deleted 表 |
|---|---|---|
| INSERT | 新增的資料列 | 空 |
| DELETE | 空 | 被刪除的資料列 |
| UPDATE | 更新後的新資料列 | 更新前的舊資料列 |
CREATE TRIGGER trg_Audit_Employee
ON dbo.Employee
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
INSERT INTO dbo.Employee_Audit (EmpID, ActionType, ChangedData, ChangeTime)
SELECT
COALESCE(i.EmpID, d.EmpID),
CASE WHEN i.EmpID IS NULL THEN 'DELETE'
WHEN d.EmpID IS NULL THEN 'INSERT'
ELSE 'UPDATE' END,
(SELECT i.* FOR JSON AUTO), -- 或自訂格式
GETDATE()
FROM inserted i
FULL JOIN deleted d ON i.EmpID = d.EmpID;
END;
CREATE TRIGGER trg_Check_Order_Amount
ON dbo.OrderDetail
AFTER INSERT, UPDATE
AS
BEGIN
IF EXISTS (
SELECT 1 FROM inserted i
JOIN dbo.[Order] o ON i.OrderID = o.OrderID
GROUP BY o.OrderID
HAVING SUM(i.LineTotal) > o.CreditLimit
)
BEGIN
RAISERROR('訂單明細總額超過信用額度', 16, 1);
ROLLBACK TRANSACTION;
END
END;
CREATE TRIGGER trg_Update_Product_Sales
ON dbo.SalesOrderDetail
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
UPDATE p
SET TotalQtySold = ISNULL(p.TotalQtySold, 0) + ISNULL(i.QtyDelta, 0) - ISNULL(d.QtyDelta, 0)
FROM dbo.Product p
JOIN (
SELECT ProductID, SUM(OrderQty) AS QtyDelta FROM inserted GROUP BY ProductID
) i ON p.ProductID = i.ProductID
LEFT JOIN (
SELECT ProductID, SUM(OrderQty) AS QtyDelta FROM deleted GROUP BY ProductID
) d ON p.ProductID = d.ProductID;
END;
UPDATE(col) 或 COLUMNS_UPDATED() 判斷特定欄位是否被修改,避免不必要邏輯。sp_configure 'nested triggers' 關閉。inserted/deleted 有索引——它們是掃描存取,大量資料時效能下降快。RECURSIVE_TRIGGERS 或自行防禦)。MERGE 陳述式同時產生 INSERT/UPDATE/DELETE 三種動作,邏輯需涵蓋三種情況。PRINT 'TRIGGER FIRED'; SELECT * FROM inserted; SELECT * FROM deleted; 快速觀察資料流向。sys.dm_exec_trigger_stats 監控觸發器執行頻率與耗時。