SQL Server基础:触发器实现增删改,数据验证及同步到新表

SQL Server中触发器常用于对一个表的更新、插入及删除后操作,和Oracle触发器类似,都有after触发器类型,但SQL Server没有before类型。

原理不多讲,上一张网上的原理图,差不多就很清楚了.

下面通过一个例子实现在SQL Server 中通过触发器删除、插入和修改数据并同步到新表

 1 ---创建一张表
 2 create table test_01
 3 (
 4    id int identity(1,1)  primary key,
 5    userID  int not null,
 6    name varchar(50)  not null,
 7    sex nvarchar(2)  not null,
 8    age int null
 9 )
10 
11 ---复制表结构到新表
12 select * into test_02 from test_01

然后,我们创建一个触发器

 1 --已存在,先删除
 2 if(exists (select * from  sysobjects where xtype='tr' and name='tri_test01'))
 3 begin
 4   drop trigger tri_test01
 5   print '已删除'
 6   end
 7   go
 8 
 9   ---创建触发器
10 create trigger tri_test01 on test_01
11 after insert,update,delete
12 as
13 begin
14     --禁止返回受影响行数
15     --SET NOCOUNT ON;
16 
17     declare  @isDel  bit  =  0
18     declare  @isIns  bit  =  0
19     declare  @changeType varchar(20)
20 
21     -- 如果在DELETED内部临时触发表找到记录,说明旧数据被删除 
22     if  exists( select  top  1  1  from deleted)
23        set  @isDel  =  1
24     
25     -- 如果在inserted内部临时触发表找到记录,说明有新数据插入     
26     if  exists( select  top  1  1  from inserted)
27          set  @isIns  =  1  
28 
29     -- 如果两个表都有记录,说明触发器是执行更新触发
30     if  @isIns  =  1  and  @isDel  =  1 
31         set @changeType='UPDATE'
32 
33     -- 如果变量@i值被变更为1,而变量@d没有变更,说明触发器是执行插入触发    
34     if  @isIns  =  1  and  @isDel  =  0
35         set @changeType='INSERT'
36  
37     -- 下面判断成立,说明说明触发器是执行删除触发    
38     if  @isIns  =  0  and  @isDel  =  1
39         set @changeType='DELETE'
40 
41     declare @userID int,@age int,@sex nvarchar,@maxid int
42     if(@changeType='INSERT')
43            begin
44          print(' 插入 ')
45          select @userID=userID,@age=age,@sex=sex from inserted
46 
47          ---如果触发器类型是before,此处可以判断ID是否存在重复
48          ---可惜SQL Server不支持before触发器
49         --if exists ( select 1 from test_01  where userID = @userID )
50         --  begin
51         --      print '用户ID不能重复 '
52         --      rollback transaction   --回滚
53         --  end
54         
55         if(@age>=200 AND @age is not null)
56           begin
57               print '人不可能长命百岁 '
58               rollback transaction   --回滚
59           end
60         else if(@sex!='' AND @sex!='')
61           begin
62               print '人不可能不男不女 '
63               rollback transaction   --回滚
64           end
65          else
66            begin    
67              insert into test_02(userID,name,sex,age)
68              select userID,name,sex,age from inserted  --插入到新表
69            end
70         end
71         ----
72       else if(@changeType='UPDATE')
73       begin
74         print ('更新')
75         if UPDATE(age)  ---更新age字段
76         begin
77               update test_02 set age  = inserted.age
78               from test_02 ,deleted,inserted
79               where test_02.age = deleted.age
80         end
81       end
82       ----
83       else if(@changeType='DELETE')
84       begin
85          select  @maxid = userID  from  deleted; 
86         if exists ( select count(1) from  test_02  where userID = @maxid )
87         begin 
88            delete  from test_02  where  userID = @maxid;    
89         end
90       end
91 end

以上触发器中,如果要判断一个用户ID是否已经存在,假设我没有为这个ID加入主键,想通过触发器判断,那么alter触发器不能实现,可以在评论说说你的解决方法.

如果触发器为更新,那么需要先删除新表已有数据,再新插入数据。例子中给的age字段只是示例,实际操作中建议以主键字段来判断。

删除的情况下,只用判断主键是否存在,已存在同步删除就OK了。

看看实际效果。。。

由于插入的时候存在触发验证的情况,若验证不通过将回滚操作,但已生成的主键值不会跟着回滚,所以两张表的主键ID(此处为自动生成的主键),可能有所不同.

 

posted @ 2021-03-18 10:56  Healer2047  阅读(2239)  评论(1编辑  收藏  举报