2014-03-07 61 views
1
CREATE TABLE Account(
    account_no int, 
    balance real, 
    type_code int, 
    branch_no int, 
    Bcode int, 
    customer_no int, 

    CONSTRAINT account_pk PRIMARY KEY (account_no), 
    CONSTRAINT check_balance CHECK (balance>=0) 
); 

alter TRIGGER tr_check_accounts_in_accountTBL 
ON account INSTEAD OF INSERT 
AS 
BEGIN 
DECLARE @count int 
DECLARE @bcode int 
DECLARE @cusNo int 

SELECT @bcode=bcode,@cusNo=customer_no 
FROM inserted; 

SELECT @count=COUNT(a.account_no) 
FROM account a 
WHERE [email protected] AND a.customer_no = @cusNo 
print @count; 

IF(@count<=5) 
    commit transaction 
ELSE 
     rollback transaction 

END 

INSERT INTO account(account_no,balance,type_code,bcode,branch_no,customer_no) 
VALUES(1,60000,1,1,1,1); 

当我尝试将数据插入上述帐户表时,触发器触发并始终回滚事务。我不明白为什么。任何人都可以请解释 谢谢。插入触发器时不考虑条件是否触发

错误显示如下:

消息3609,级别16,状态1,2号线
在触发器中结束交易。该批次已被中止。

+1

您需要重写触发器 - 假设它始终在“插入”中只有一行 - 这是** NOT * * 案子!如果您插入多行,则“插入”将包含**多于一行**,并且您的分配“SELECT @ bcode = bcode,@ cusNo = customer_no FROM inserted;'将任意选择其中一行(并忽略其余的部分)。您的触发器**需要在'Inserted'中插入多行** –

+1

另外,由于您使用的是INSTEAD OF INSERT触发器,因此您需要在触发器中执行INSERT ** 。我不会在任何地方看到......在INSERT之后,您不应该调用“COMMIT” - 这会自动发生。如果您想中止操作,请使用'ROLLBACK'。 –

+0

所以你试图做的是创建一个表,其中任何特定的'bcode'和'customer_no'组合不能超过5行? –

回答

1

正如我在评论说 - 通常情况下,Inserted可以和将包含多行和当前触发不能与处理。

但是,如果你知道并能保证你永远只打算在一次插入一行 - 那么你的触发仍然有缺陷:由于您使用的INSTEAD OF INSERT

  • ,在情况一切都OK了,你必须实际INSERT - 这触发运行,而不是通常的SQL插入....所以,如果一切顺利,你需要做的插入操作

  • 也:唐别叫触发器中的- 如果一切正常,它将自动处理。仅使用ROLLBACK中止的INSERT如果情况不好

你需要使用类似:

CREATE TRIGGER tr_check_accounts_in_accountTBL 
ON dbo.Account INSTEAD OF INSERT 
AS 
BEGIN 
    DECLARE @count int 
    DECLARE @bcode int 
    DECLARE @cusNo int 

    SELECT @bcode = bcode, @cusNo = customer_no 
    FROM inserted; 

    SELECT @count = COUNT(a.account_no) 
    FROM dbo.Account a 
    WHERE a.bcode = @bcode AND a.customer_no = @cusNo 

    IF(@count <= 5) 
     -- all is well, now DO the insert! 
     INSERT INTO dbo.Account (account_no, balance, type_code, branch_no, Bcode, customer_no) 
      SELECT 
       account_no, balance, type_code, branch_no, Bcode, customer_no 
      FROM 
       Inserted 
    ELSE 
     -- situation is not good -> abort the INSERT 
     ROLLBACK TRANSACTION 
END 

另外:我会强烈建议使用real你的钱值 - 使用DECIMAL(p, s)代替! REAL在舍入错误和缺乏精确度方面非常糟糕......

+0

你的答案是很清楚的,感谢你 – Roledenez

+0

但有一个逻辑错误,这个触发器允许插入5个以上的帐户到同一个bcode和customer_no账户表 – Roledenez

+0

@SelaruSinbath:它允许** 6 **行 - 因为你正在检查'<= 5'(在发生'INSERT'之前)它如果已经有5行,并且允许插入第六行,**将成功**。你需要明白:当你检查'<= 5'时,新的'INSERT'还没有发生**呢!你以后会这样做。所以,如果你想限制它最多5行,你需要检查'@count <5'(不是'<=') –