最近在做一个权限管理的模块,原本设计的数据库表之间有大量的外键关系,而这些外键之间的结构是非树状的,所以使用ms sql来建立数据库中总要报错。最后决定用触发器来代替外键,基本思想就是在原本需要用外键的地方,在主键表上建立after update和after delete的触发器。
下面是一些例子
表Menu1中有列Name,而表Menu2中列Father,原本前者是后者的外键,现在用触发器代替。
after update触发器
If exists(select * from sysobjects where id=object_id(N'[dbo].[triggertest ]') and objectproperty(id,N'istrigger')=1)
DROP TRIGGER triggertest
go
create trigger triggertest on Menu1
after update
as
if update(Name)
begin
update Menu2 set Father = (select Name from inserted)
where Father = (select Name from deleted)
end
after delete触发器
If exists(select * from sysobjects where id=object_id(N'[dbo].[triggertest2 ]') and objectproperty(id,N'istrigger')=1)
DROP TRIGGER triggertest2
go
create trigger triggertest2 on Menu1
after delete
as
if (select count(*) from deleted ) > 0
begin
delete from Menu2 where Father = (select Name from deleted)
end
其中语句
If exists(select * from sysobjects where id=object_id(N'[dbo].[XXX ]') and objectproperty(id,N'istrigger')=1)
DROP TRIGGER XXX
用于判断触发器XXX 是否已经存在,若存在将其从库中剔除。
语句 if update(XX)是判断表中的XX列是否有被更新,当我们对表中XX列执行update ... set ....操作或insert操作时,update(XX)为真。在这里我们还有另一种方式来判定某列是否被更新,那就是使用
IF (COLUMNS_UPDATED())语句,它用语测试是否插入或更新了提及的列,仅用于 INSERT 或 UPDATE 触发器中。COLUMNS_UPDATED 返回 varbinary 位模式,表示插入或更新了表中的哪些列。CLUMNS_UPDATED 函数以从左到右的顺序返回位,若表中中有5列,分别为C1,C2,C3,C4,C5,其中C1,C2,C5被更新的话,那么它将返回10011,依此类推。在 INSERT 操作中 COLUMNS_UPDATED 将对所有列返回 TRUE 值,因为这些列插入了显式值或隐性 (NULL) 值。如果需要判断表中某些列是否被更新,则需要用到updated-bitmask即整型掩码,对于刚才提到的拥有5列的那个表,如果我们想知道C1有没有被更新,那么只要用if (COLUMNS_UPDATED() & 1) 就可以啦。若要判断C1,C4有是否有被更新,则用9(1001)代替1就可以啦。
语句 if (select count(*) from deleted ) > 0 用于判断表deleted是否为空,我们还有许多办法来判断表是否为空
select * from test
if @@rowcount >0
-------------------------------------------------------------
if exists (select * from test)
---------------------------------------------------------------
if (select top 1 id from test) is null
使用这个语句的目的在于防止触发器的间接或直接递归。比如说在表p1中,我们建立after update触发器,在触发的事件中我们delete表p2的某个符合id > 0的行,然后在表p2中,我们建立after delete触发器,在触发事件中,我们update表p2。那么如果没有加上如上的判断表是否为空的语句,那么将会出现“触发器超过最大允许嵌套次数”的错误。