建立触发器检查单据
主从表金额一致检查,先保存主表item_table,再保存从表items_table,保存items_table时根据id进行检查,sum(price)=price.
如果从数据库想办法控制,怎么建立触发器来控制呢?item_table:
id  price
 1   20items_table:
autoid  id   price
 1       1    10
 2       1     6
 3       1     4create TRIGGER [dbo].pricecheck ON items_table 
FOR INSERT
--FOR INSERT, UPDATE, DELETE 
AS
begin
 declare
 @id int
set @id=(select  id from inserted) 
if (select round(price,2) from [item_table] where id=@id) 
<> (select round(sum(isnull(price,0)),2) from [items_table] where id=@id)
RAISERROR ('金额不一致不允许保存,请检查!'  , 16, 1)
end
这样建立触发器后发现,金额等于也无法保存,因为插入从表第一条记录时无法取到sum(price)
该怎样修改?

解决方案 »

  1.   

    --Modified version ,Note 1 points, 2 points
    create TRIGGER [dbo].pricecheck ON items_table 
    AFTER INSERT
    --1.AFTER代替FOR
    AS
    begin
     declare
     @id int
    set @id=(select  id from inserted) if (select round(price,2) from [item_table] where id=@id) 
    <> (select round(sum(isnull(price,0)),2) from [items_table] where id=@id)
    begin
        -- 2.直接回滚 ,数据就不会保存了, 
       rollback
    end
    end
      

  2.   

    这种情况,我不认为,检查在触发器时做好。
    而是在所有可能增删改items_table表时,都做事务检查比较好。虽然会要写好多地方,但这是必须的。
    因为比如你在插入时,要插入N条items_table记录,对整体再做检查,所以,这个事务是一个整体的。
      

  3.   

    最好用存储过程,将所有操作放在一个事务里:CREATE PROCEDURE <Procedure_Name, sysname, ProcedureName> 
    @ID INT,
    @Result SMALLINT OUTPUT -- -1表示金额不一致不允许保存,1表示成功
    AS
    BEGIN
    SET NOCOUNT ON;    SET XACT_ABORT ON
        
        BEGIN TRANSACTION
        
        DECLARE @A INT,
    @B INT

    SELECT @A=ROUND(price,2)
    FROM [item_table] WITH(NOLOCK)
    WHERE ID=@ID

    SELECT @B=ROUND(SUM(ISNULL(price,0)),2)
    FROM [items_table] WITH(NOLOCK)
    WHERE ID=@ID

    IF (@A<>@B)
    BEGIN
    SET @Result=-1
    RETURN
    END
    ELSE
    BEGIN
    --执行保存代码
    END

    SET @Result=1
        
        COMMIT TRANSACTION
    END
    GO
      

  4.   

    这是没有办法的办法,多用于原系统程序无法干预的情况下另外想变通办法达到检查的目的。
    所以还得用触发器来做SQL的检查,没办法加存储过程到程序里调用。
    请大家想想办法