SQL Server 提供三類觸發器:DML、DDL、登入。本文專注 DDL 觸發器 (回應 CREATE/ALTER/DROP 等結構定義語句) 與 登入觸發器 (回應 LOGON 事件),示範稽核資料庫/伺服器層級 DDL 變更、阻擋建立登入帳號、限制特定帳號登入時間。
USE master; GO
CREATE TABLE dbo.ChangeAttempt (
EventData xml NOT NULL,
AttemptDate datetime NOT NULL DEFAULT GETDATE(),
DBUser char(50) NOT NULL
); GO
CREATE TRIGGER db_trg_RestrictINDEXChanges
ON DATABASE
FOR CREATE_INDEX, ALTER_INDEX, DROP_INDEX
AS
BEGIN
SET NOCOUNT ON;
INSERT dbo.ChangeAttempt (EventData, DBUser)
VALUES (EVENTDATA(), USER);
END; GO
-- 測試
CREATE NONCLUSTERED INDEX ni_ChangeAttempt_DBUser ON dbo.ChangeAttempt(DBUser); GO
SELECT EventData FROM dbo.ChangeAttempt; GO

USE master; GO
CREATE TRIGGER srv_trg_RestrictNewLogins
ON ALL SERVER
FOR CREATE_LOGIN
AS
BEGIN
PRINT 'No login creations without DBA involvement.';
ROLLBACK;
END; GO
-- 測試 → 會被阻擋並回滾
CREATE LOGIN johny WITH PASSWORD = '123456'; GO
-- 移除觸發器
DROP TRIGGER srv_trg_RestrictNewLogins ON ALL SERVER; GO

⚠ 警告:伺服器層級 DDL 觸發器設定不當可能導致無法管理伺服器,請極度謹慎測試後再部署生產環境。
-- 建立測試帳號與稽核表
CREATE LOGIN nightworker WITH PASSWORD = '123b3b4'; GO
CREATE DATABASE ExampleAuditDB; GO
USE ExampleAuditDB; GO
CREATE TABLE dbo.RestrictedLogonAttempt (
LoginNM sysname NOT NULL,
AttemptDT datetime NOT NULL
); GO
-- 建立登入觸發器
USE master; GO
CREATE TRIGGER trg_logon_attempt
ON ALL SERVER
WITH EXECUTE AS 'sa'
FOR LOGON
AS
BEGIN
IF ORIGINAL_LOGIN() = 'nightworker'
AND DATEPART(hour, GETDATE()) BETWEEN 7 AND 17
BEGIN
ROLLBACK; -- 拒絕登入
INSERT ExampleAuditDB.dbo.RestrictedLogonAttempt (LoginNM, AttemptDT)
VALUES (ORIGINAL_LOGIN(), GETDATE());
END
END; GO
-- 查看稽核記錄
USE ExampleAuditDB; GO
SELECT * FROM dbo.RestrictedLogonAttempt; GO
-- 清理
DROP TRIGGER trg_logon_attempt ON ALL SERVER; GO
DROP DATABASE ExampleAuditDB; GO
