首頁 SQL Trigger Example
文章
Cancel

SQL Trigger Example

透過Trigger紀錄資料異動的紀錄

1.首先會有一個主資料表

Source Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  USE [DemoDB]
  GO
  /****** Object:  Table [dbo].[Member]    Script Date: 2022/10/30 下午 11:23:35 ******/
  SET ANSI_NULLS ON
  GO
  SET QUOTED_IDENTIFIER ON
  GO
  CREATE TABLE [dbo].[Member](
      [UserID] [int] IDENTITY(1,1) NOT NULL,
      [UserName] [varchar](10) NULL,
      [UserEmail] [varchar](50) NULL,
   CONSTRAINT [PK_Member] PRIMARY KEY CLUSTERED 
  (
      [UserID] ASC
  )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  ) ON [PRIMARY]
  GO
  SET IDENTITY_INSERT [dbo].[Member] ON 
  GO
  INSERT [dbo].[Member] ([UserID], [UserName], [UserEmail]) VALUES (1, N'haha', N'A@ya.com')
  GO
  INSERT [dbo].[Member] ([UserID], [UserName], [UserEmail]) VALUES (2, N'sdsa', N'B@yahoo.com')
  GO
  INSERT [dbo].[Member] ([UserID], [UserName], [UserEmail]) VALUES (3, N'CDE', N'C@yahoo.com')
  GO
  INSERT [dbo].[Member] ([UserID], [UserName], [UserEmail]) VALUES (4, N'de', N'D@yahoo.com')
  GO
  INSERT [dbo].[Member] ([UserID], [UserName], [UserEmail]) VALUES (5, N'E', N'E@yahoo.com')
  GO
  INSERT [dbo].[Member] ([UserID], [UserName], [UserEmail]) VALUES (6, N'dcdc', N'F@yahoo.com')
  GO
  SET IDENTITY_INSERT [dbo].[Member] OFF
  GO

Desktop View

2.建立用來記錄異動資料的資料表

Source Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    USE [DemoDB]
  GO

  /****** Object:  Table [dbo].[Member_Backup]    Script Date: 2022/10/30 下午 11:18:40 ******/
  SET ANSI_NULLS ON
  GO

  SET QUOTED_IDENTIFIER ON
  GO

  CREATE TABLE [dbo].[Member_Backup](
      [UserID] [int] NULL,
      [UserName] [varchar](10) NULL,
      [UserEmail] [varchar](50) NULL
  ) ON [PRIMARY]
  GO

Desktop View

3.在主資料表底下建立Trigger

如圖 Desktop View

方法1:透過變數先將被變更的第一項內容記錄下來

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  USE [DemoDB]
  GO

  /****** Object:  Trigger [dbo].[triMember]    Script Date: 2022/10/30 下午 11:31:54 ******/
  SET ANSI_NULLS ON
  GO

  SET QUOTED_IDENTIFIER ON
  GO

  -- =============================================
  -- Author:		<Author,,Name>
  -- Create date: <Create Date,,>
  -- Description:	<Description,,>
  -- =============================================
  CREATE TRIGGER [dbo].[triMember]
     ON  [dbo].[Member]
     AFTER UPDATE
  AS 
  BEGIN
      -- 宣告變數,用來記錄被改變的資料內容
      SET NOCOUNT ON;
      DECLARE @UserID int;
      DECLARE @UserName varchar(50)
      DECLARE @UserEmail varchar(50)
      -- 透過Select來獲得第一項被改變的欄位內容
        select @UserID=UserID,@UserName =UserName ,@UserEmail=UserEmail from deleted    --from deleted紀錄的是被覆蓋的舊數值

      -- select @UserID=UserID,@UserName =UserName ,@UserEmail=UserEmail from INSERTED --from INSERTED紀錄的是要蓋過去的新數值

        PRINT @UserID
        PRINT @UserName
        PRINT @UserEmail
  
        -- 將被改變的內容插到新的一列中
       INSERT INTO Member_Backup(UserName,UserEmail) values ( @UserName,@UserEmail)
  END
  GO

  ALTER TABLE [dbo].[Member] ENABLE TRIGGER [triMember]
  GO

方法2:Insert時 Select來找到被改變的那一列
參考至此

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    USE [DemoDB]
    GO

    /****** Object:  Trigger [dbo].[triMember]    Script Date: 2022/10/30 下午 11:39:46 ******/
    SET ANSI_NULLS ON
    GO

    SET QUOTED_IDENTIFIER ON
    GO

    -- =============================================
    -- Author:		<Author,,Name>
    -- Create date: <Create Date,,>
    -- Description:	<Description,,>
    -- =============================================
    CREATE TRIGGER [dbo].[triMember]
       ON  [dbo].[Member]
       AFTER UPDATE
    AS 
    BEGIN
 
         INSERT INTO Member_Backup(UserName,UserEmail)  
             SELECT i.UserName,i.UserEmail
	        FROM inserted AS i
	        UNION
	        SELECT d.UserName,d.UserEmail
	        FROM deleted AS d;
    END
    GO

    ALTER TABLE [dbo].[Member] ENABLE TRIGGER [triMember]
    GO

補充 : Mssql Mail

Desktop View
建立一個一旦內容改變,舊使用MSSQL發信通知的Trigger,Trigger的寫法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
USE [DemoTrigger]
GO

/****** Object:  Trigger [dbo].[UserInfo_UpdateTrigger]    Script Date: 2023/3/1 下午 04:55:12 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TRIGGER [dbo].[UserInfo_UpdateTrigger] -- TRIGGER 的名稱
   ON  [dbo].[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 @mybody varchar (max)
        DECLARE @userId INT;
        DECLARE @dataCount INT;
	    DECLARE @UserName varchar (max);
        PRINT 'Set log start.'
        -- 新增資料使用 inseted,刪除資料使用 deleted,更新資料(Update)的話則是都會有
        SELECT @userId=UserId, @dataCount=DataCount , @UserName=UserName FROM deleted;
  
        PRINT 'Set log success.'
   -- 下面 開始撰寫發信內容
		    BEGIN
		    set @mybody = '測試' + CONVERT(varchar(max),@UserId)  + '  ' + CONVERT(varchar(max),@DataCount)  + ' ' +  @UserName;
		      EXEC msdb.dbo.sp_send_dbmail
		      @profile_name = 'test',
		      @recipients = 'q12389@yahoo.com.tw',
		      @subject = 'Database Record Updated',
		      @body = @mybody 
		    end
    END
    ELSE
    -- else 條件成立則執行
    BEGIN
        PRINT 'Nothing to do.'
    END
END
GO

ALTER TABLE [dbo].[UserInfo] ENABLE TRIGGER [UserInfo_UpdateTrigger]
GO
本文由作者按照 CC BY 4.0 進行授權