主表rdrecord
id  handler
984 aaa子表 rdrecords
auid 主表id   cinvcode  unitcost
1     984      0101      12
2     984      0201      24
  
存货表inventory
cinvcode cinvdefine1
0101     
0201select * 
from rdrecord a
left join rdrecords b on a.id=b.id
left join inventory c on b.cinvcode=c.cinvcode
where a.id=984查询我是可以查到两条记录的我在触发器时,我想在主表的handler字段有字符写入时,就触发,子表中相应的存货的UNITCOST写入到存货表相应的存货的CINVDEFINE1中去CREATE TRIGGER [GHY] ON [dbo].[RdRecord] 
FOR INSERT, UPDATE, DELETE 
AS
begin
  declare @id as int
  declare @Vencode as varchar(50)
  declare @Handler as varchar(50)  select @id = id ,@Handler=CHandler  from inserted 
   
   if LEN(@Handler)<>0
   begin  
   update c
   set c.cinvdefine1=b.iunitcost
   from rdrecord a
   left join rdrecords b on a.id=b.id
   left join inventory c on b.cinvcode=c.cinvcode
   where a.id=@id
   end
end
但运行结果发现,只更改了最后一行记录,这是为什么呢?触发器应怎样写呢?

解决方案 »

  1.   


    CREATE TRIGGER [GHY] ON [dbo].[RdRecord] 
    FOR INSERT, UPDATE, DELETE 
    AS 
    begin 
      declare @id as int 
      declare @Vencode as varchar(50) 
      declare @Handler as varchar(50)   --select @id = id ,@Handler=CHandler  from inserted 
      --if LEN(@Handler) <>0 
      --begin  
      update c  set c.cinvdefine1=b.iunitcost 
      from (select * from rdrecord as t1 inner join inserted as t2 on t1.id=t2.id and len(t2.CHandler)>0 ) as  a 
      left join rdrecords b on a.id=b.id 
      left join inventory c on b.cinvcode=c.cinvcode 
      --where a.id=@id 
      --end 
    end 
      

  2.   

    CREATE TRIGGER [GHY] ON [dbo].[RdRecord] 
    FOR INSERT, UPDATE, DELETE 
    AS 
    begin 
      --declare @id as int 
      --declare @Vencode as varchar(50) 
      --declare @Handler as varchar(50)   --select @id = id ,@Handler=CHandler  from inserted 
      
      --if LEN(@Handler) <>0 
    --begin  
      update c 
      set c.cinvdefine1=b.iunitcost 
      from rdrecord a 
       join rdrecords b on a.id=b.id and len(a.CHandler)<>0
       join inventory c on b.cinvcode=c.cinvcode --即然要更新的是inventory,就没必要用左连接,用内连效率更高.
      --where a.id=@id 
      --end 
    end 
      

  3.   

    原因:一、            触发器实现的是在表的操作进行同时,自动进行的操作或者控制,在写触发器代码时必须考虑其特殊性。二、            必须限定触发器影响的记录,不能扩大。也就是说必须引用INSERTED和DELETED两个虚表限定操作的范围。三、            INSERTED和DELETED的作用域只限定触发器本身,其调用的存储过程是不能使用的。四、            写触发器必须考虑性能,因为其自动性,如果触发器性能不好是可能拖垮一个系统的。五、            必须考虑一次操作多条记录的情况,除非保证一次只操作一条记录,一般不能用变量暂存虚表的数据,否则就可能出现在批量操作情况下,触发器只处理最后一条记录的情况,这类错误可以说是触发器最常见的错误之一。六、            必须注意递归和嵌套触发器,因为触发器往往需要修改其他或者本表数据来实现其功能,这里的修改数据往往能再次触发触发器,这时就必须保证其嵌套或者递归过程不是无限的,SQL SERVER对触发器的嵌套层数有最多32的限制。七、            触发器不好调试,比起一般存储过程,触发器是在修改数据过程中触发,调试难度更大。调试过程必须考虑所有情况,比如空表插入数据、已有数据插入新数据、一次插入多行数据、修改一条数据、修改多条数据、一次删除多条数据、影响0行的修改或者删除语句等等。详见海爷的BLOG:http://blog.csdn.net/Haiwer/archive/2008/10/04/3016333.aspx
      

  4.   

    .
    貌似原来的触发器不应该只更新一条数据?这个触发器的
    FOR INSERT, UPDATE, DELETE  -- DELETE操作未作任何处理