石头园  
每日收获

最近在做一个权限管理的模块,原本设计的数据库表之间有大量的外键关系,而这些外键之间的结构是非树状的,所以使用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。那么如果没有加上如上的判断表是否为空的语句,那么将会出现“触发器超过最大允许嵌套次数”的错误。 

posted on 2006-08-16 23:07  石头仔  阅读(537)  评论(1编辑  收藏  举报