關於 TRIGGER 本篇將討論以下幾個問題
1. 什麼是 DML、DDL、DQL?
2. 什麼是 TRIGGER?
3. 如何使用 TRIGGER?
4. 情境
5. 使用建議
測試環境:
MS SQL:SQL Server 2019 Linux
SSMS:Microsoft SQL Server Management Studio 18
1. 什麼是 DML、DDL、DQL?
你可能沒有聽過 DML、DDL、DQL 這些縮寫,不過只要工作上有使用到 MSSQL,那就肯定使用過只是不知道這些縮寫罷了,說明如下
- DML(Data Manipulation Language):用於操作資料表內的資料(e.g. INSERT、UPDATE、DELETE)
- DDL(Data Definition Language):用於操作資料表(e.g. CREATE、ALTER、DROP)
- DQL(Data Query Language):用於資料查詢(e.g. SELECT)
本篇範例主要會說明如何建立在 DML 操作時會觸發的觸發程序(TRIGGER)。
2. 什麼是 TRIGGER?
MSDN 上說:「觸發程序是一種特殊的預存程序,其會在資料庫伺服器發生事件時自動執行。」
如同字面上的意思,在 INSERT、UPDATE、DELETE 等事件發生時,會觸發執行的程式。
3. 如何使用 TRIGGER?
本篇會以如何使用為主,實際運作細節會附上 MSDN 連結,有興趣的朋友可以深入研究。
CREATE TRIGGER [TRIGGER 的名稱]
ON [指定資料表]
AFTER UPDATE, INSERT, DELETE -- 觸發事件
AS
BEGIN
-- 觸發後可寫 if/else 條件
-- 下面 if 中包含兩個條件
-- 1. UPDATE(欄位名稱),不論 INSERT 或 UPDATE 嘗試成功與否,UPDATE() 都會傳回 TRUE
-- 2. EXISTS 指定測試資料列是否存在的子查詢
IF UPDATE([指定欄位]) AND EXISTS([子查詢])
-- if 條件成立則執行
BEGIN
PRINT '使用 PRINT 印出想知道的資訊'
END
ELSE
-- else 條件成立則執行
BEGIN
PRINT 'Nothing to do.'
END
END
4. 情境
- 資料表
UserInfo
中存有使用者資料, - 現在有一筆資料的
DataCount
被異動了 - 希望藉由 Trigger 在 Update 事件發生時自動將異動的紀錄寫入
UserLog
資料表中
建立UserInfo
& UserLog
兩張資料表
USE [資料庫名稱]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UserInfo](
[UserId] [int] IDENTITY(1,1) NOT NULL,
[UserName] [nvarchar](50) NOT NULL,
[DataCount] [int] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[UserLog](
[UserId] [int] NOT NULL,
[DataCount] [int] NOT NULL,
[CreateDate] [datetime] NOT NULL
) ON [PRIMARY]
GO
手動在UserInfo
資料表中加入一筆資料
UserId | UserName | DataCount |
---|---|---|
1 | Wayne | 10 |
建立 Trigger UserInfo_UpdateTrigger
CREATE TRIGGER UserInfo_UpdateTrigger -- TRIGGER 的名稱
ON [UserInfo] -- 指定資料表
AFTER UPDATE -- UPDATE 之後觸發,還有 INSERT, DELETE,多個則以 ',' 分隔
AS
BEGIN
-- 觸發後可寫 if/else 條件
-- 下面 if 中包含兩個條件
-- 1. UPDATE(欄位名稱),不論 INSERT 或 UPDATE 嘗試成功與否,UPDATE() 都會傳回 TRUE
-- 2. EXISTS 指定測試資料列是否存在的子查詢
IF UPDATE([DataCount]) AND EXISTS(SELECT Count(1) FROM [UserInfo] WHERE DataCount > 0)
-- if 條件成立則執行
BEGIN
DECLARE @userId INT;
DECLARE @dataCount INT;
PRINT 'Set log start.'
-- 新增資料使用 inseted,刪除資料使用 deleted,更新資料(Update)的話則是都會有
SELECT @userId=UserId, @dataCount=DataCount FROM deleted;
INSERT INTO UserLog (UserId, DataCount, CreateDate)
VALUES (@userId, @dataCount, GETDATE());
-- 使用 PRINT 印出想知道的資訊
PRINT 'Set log success.'
END
ELSE
-- else 條件成立則執行
BEGIN
PRINT 'Nothing to do.'
END
END
建立完成後可以在 SSMS 中資料表下的觸發程序中找到剛建立的 Trigger
右鍵可以開啟選單,進行修改、停用、刪除等操作
建立異動UserInfo
中DataCount
欄位的 Update
UPDATE UserInfo
SET DataCount = 20
WHERE UserId = 1
執行後可以看到兩次的「(1 個資料列受到影響)」
分別是 Insert UserLog & Update UserInfo 兩個操作
Set log start.
(1 個資料列受到影響)
Set log success.
(1 個資料列受到影響)
完成時間: 2021-02-11T14:39:19.2255724+08:00
可以看到UserLog
中新增一筆異動前的紀錄
UserInfo
中DataCount
也更新為 20 了
5. 使用建議
雖然 Trigger 使用上很簡單,維護起來卻不是那麼容易,若是有多個複雜邏輯時,在除錯上就更是困難了,請謹慎評估後再使用。
另外建議不要在團隊不知情的情況下使用 Trigger,避免遇到問題時同事花了大把時間才發現原來資料寫入是在資料庫中觸發的,雖然 git 中不會有 commit 紀錄,使用前還是經由團隊開會後決議再使用比較保險。