在不考虑if条件的情况下插入触发器

时间:2014-03-07 06:06:03

标签: sql sql-server triggers

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 a.bcode=@bcode 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);

当我尝试将数据插入到Account表上方时,触发器始终触发并回滚事务。我不明白为什么。任何人都可以请解释 谢谢。

错误显示如下:

  

Msg 3609,Level 16,State 1,Line 2
  交易在触发器中结束。批次已中止。

1 个答案:

答案 0 :(得分:1)

正如我在评论中所说 - 通常Inserted可以并且将包含多行,而您当前的触发器无法处理。

但如果您知道并且可以保证您一次只能插入一行 - 那么您的触发器仍有缺陷:

  • ,因为您使用的是INSTEAD OF INSERT,如果一切正常,您必须执行INSERT - 此触发器已运行而不是通常的SQL插入....所以如果一切顺利,你需要进行插入操作

  • 另外:不要在触发器中调用COMMIT - 如果一切正常,它将自动处理。如果情况不佳,仅使用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在舍入错误和缺乏准确性方面非常糟糕.....