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
同时认为,插入表中可能存在多个记录。如果这些记录针对多个客户,并且任何客户都会导致此触发器回滚事务,则不会应用那些未违反您的规则的客户的更新。这可能永远不会发生(如果您的应用程序一次不会更新多个客户的记录),或者可能是预期的行为。
试试这个,而不是触发器中的当前查询。我认为这可能有效。
我的语法可能有点偏离,但你会得到一般想法。
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
这将返回客户+银行组合多少次存在。这是你想要的限制。
如果您发布的代码或XML,** **请在高亮文本编辑器的线,然后点击“代码“编辑器工具栏上的按钮(101 010)可以很好地格式化和语法突出显示它! – 2010-09-16 14:50:51
我的不好。感谢编辑。 – 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的修改。
您是否将NUMBER_FOR_BANK计算为触发器的一部分来维护它?您是否也必须保护自己免于直接更新NUMBER_FOR_BANK(例如UPDATE ACCOUNT_CUSTOMER SET NUMBER_FOR_BANK = 1)?这与OP目前的做法似乎更加复杂。 – 2010-09-16 16:42:36
没有必要“保护自己免受NUMBER_FOR_BANK的直接更新” - 因为约束条件不能以脏数据结束。您可以在该列中留有空白,但不能有重复。 – 2010-09-16 18:27:22
是的,@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
我不知道插入的表可以有多个记录 – Nipuna 2010-09-17 03:40:41