SQL触发器无法正常工作

问题描述:

这里是我拥有的2个表,我想实现一个触发器,即客户不能超过一个银行的5个帐户,但总共可以有超过5个帐户SQL触发器无法正常工作

CREATE TABLE ACCOUNT(
    ACCOUNT_NO VARCHAR(20) NOT NULL, 
    BALANCE REAL, 
    BANK_CODE VARCHAR(20), 
    BRANCH_NO VARCHAR(25), 
    ACCOUNT_CODE VARCHAR(20), 
    PRIMARY KEY(ACCOUNT_NO), 
); 

CREATE TABLE ACCOUNT_CUSTOMER(
    CUS_NO VARCHAR(20) NOT NULL, 
    ACCOUNT_NO VARCHAR(20) NOT NULL, 

    PRIMARY KEY(CUS_NO,ACCOUNT_NO), 
     FOREIGN KEY(ACCOUNT_NO) REFERENCES ACCOUNT(ACCOUNT_NO), 
    ); 

继承人触发我写,而是因为它会检查所有的银行,而不是一个单一银行的所有账户我不能创建总计超过5个帐户。

CREATE TRIGGER TRIGGER1 
    ON ACCOUNT_CUSTOMER 
    FOR INSERT,UPDATE 
    AS BEGIN 
    DECLARE @COUNT INT 
    DECLARE @CUS_NO VARCHAR(20) 

    SELECT @COUNT=COUNT(AC.ACCOUNT_NO) 
    FROM INSERTED I,ACCOUNT_CUSTOMER AC 
    WHERE I.CUS_NO=AC.CUS_NO 
    GROUP BY(AC.CUS_NO) 

    IF @COUNT>5 
    ROLLBACK TRANSACTION 
    END 

问题是WITHIN THE GROUPBY功能我猜。

我会尝试这样的事:

这个替换您的触发

SELECT @COUNT=COUNT(AC.ACCOUNT_NO) 
FROM INSERTED I,ACCOUNT_CUSTOMER AC 
WHERE I.CUS_NO=AC.CUS_NO 
GROUP BY(AC.CUS_NO) 

IF @COUNT>5 
ROLLBACK TRANSACTION 

的这一部分:

IF EXISTS (
     SELECT COUNT(a.ACCOUNT_NO) 
     FROM INSERTED i 
       JOIN ACCOUNT a ON i.ACCOUNT_NO = a.ACCOUNT_NO 
       JOIN ACCOUNT_CUSTOMER c ON i.CUS_NO = c.CUS_NO 
     GROUP BY c.CUS_NO, a.BANK_CODE 
     HAVING COUNT(a.ACCOUNT_NO) >= 5 
    ) 
    ROLLBACK TRANSACTION 

同时认为,插入表中可能存在多个记录。如果这些记录针对多个客户,并且任何客户都会导致此触发器回滚事务,则不会应用那些未违反您的规则的客户的更新。这可能永远不会发生(如果您的应用程序一次不会更新多个客户的记录),或者可能是预期的行为。

+0

我不知道插入的表可以有多个记录 – Nipuna 2010-09-17 03:40:41

试试这个,而不是触发器中的当前查询。我认为这可能有效。

我的语法可能有点偏离,但你会得到一般想法。

SELECT @COUNT=MAX(COUNT(AC.ACCOUNT_NO)) 
FROM INSERTED I 
INNER JOIN ACCOUNT_CUSTOMER AC ON I.CUS_NO=AC.CUS_NO 
INNER JOIN ACCOUNT A ON AC.ACCOUNT_NO = A.ACCOUNT_NO 
GROUP BY(AC.CUS_NO, A.BANK_CODE) 

查询的麻烦在于您只能通过唯一的客户标识符进行搜索。

您的查询必须一起搜索唯一客户和银行标识符的计数。我会留下准确的查询到你,但这里就是你在伪想要的东西:

SELECT COUNT(customer_id) 
FROM table_name 
WHERE customer_id = customer_id_to_validate 
AND bank_id = bank_id_to_validate 

这将返回客户+银行组合多少次存在。这是你想要的限制。

+1

如果您发布的代码或XML,** **请在高亮文本编辑器的线,然后点击“代码“编辑器工具栏上的按钮(101 010)可以很好地格式化和语法突出显示它! – 2010-09-16 14:50:51

+0

我的不好。感谢编辑。 – bobwaycott 2010-09-16 23:51:36

这是很容易与约束来实现:

CREATE TABLE ACCOUNT(
    ACCOUNT_NO VARCHAR(20) NOT NULL, 
    BALANCE REAL, 
    BANK_CODE VARCHAR(20), 
    BRANCH_NO VARCHAR(25), 
    ACCOUNT_CODE VARCHAR(20), 
    PRIMARY KEY(ACCOUNT_NO), 
    UNIQUE(ACCOUNT_NO,BANK_CODE) 
); 

CREATE TABLE ACCOUNT_CUSTOMER(
    CUS_NO VARCHAR(20) NOT NULL, 
    ACCOUNT_NO VARCHAR(20) NOT NULL, 
     BANK_CODE VARCHAR(20), 
    NUMBER_FOR_BANK INT NOT NULL CHECK(NUMBER_FOR_BANK BETWEEN 1 AND 5),  
    PRIMARY KEY(CUS_NO,ACCOUNT_NO), 
    UNIQUE(CUS_NO,BANK_CODE,NUMBER_FOR_BANK), 
     FOREIGN KEY(ACCOUNT_NO, BANK_CODE) REFERENCES ACCOUNT(ACCOUNT_NO, BANK_CODE), 
    ); 

编辑:有时会触发不火。只有可信约束100%保证了数据的完整性。

要插入,我会用数字表:

INSERT INTO ACCOUNT_CUSTOMER(
    CUS_NO, 
    ACCOUNT_NO, 
     BANK_CODE, 
    NUMBER_FOR_BANK 
    ) 
SELECT TOP 1 @CUS_NO, 
    @ACCOUNT_NO, 
     @BANK_CODE, 
    NUMBER 
FROM dbo.Numbers WHERE NUMBER BETWEEN 1 AND 5 
AND NOT EXISTS(SELECT * FROM ACCOUNT_CUSTOMER WHERE [email protected]_NO AND [email protected]_CODE) 

我会用一个触发器,禁止BANK_CODE的修改。

+0

您是否将NUMBER_FOR_BANK计算为触发器的一部分来维护它?您是否也必须保护自己免于直接更新NUMBER_FOR_BANK(例如UPDATE ACCOUNT_CUSTOMER SET NUMBER_FOR_BANK = 1)?这与OP目前的做法似乎更加复杂。 – 2010-09-16 16:42:36

+0

没有必要“保护自己免受NUMBER_FOR_BANK的直接更新” - 因为约束条件不能以脏数据结束。您可以在该列中留有空白,但不能有重复。 – 2010-09-16 18:27:22

+0

是的,@AlexKuznetsov,请详细说明你的方法。 – 2010-09-16 18:30:36

感谢您的答案,经历了所有后,我想出了这个解决方案。我插入一个嵌套查询taht会给我BANKCODE和代码我得到的计数

CREATE TRIGGER TRIGGER1 
ON ACCOUNT_CUSTOMER 
FOR INSERT,UPDATE 
AS BEGIN 
DECLARE @COUNT INT 
DECLARE @CUS_NO VARCHAR(20) 

SELECT @COUNT=COUNT(*) 
FROM ACCOUNT_CUSTOMER AC, ACCOUNT A 
WHERE A.ACCOUNT_NO=AC.ACCOUNT_NO AND A.BANK_CODE= 
       (SELECT A.BANK_CODE 
       FROM DIT09C_0293_ACCOUNT A, INSERTED I 
       WHERE A.ACCOUNT_NO=I.ACCOUNT_NO 
       ) 
    IF @COUNT>5 
     ROLLBACK TRANSACTION 
END