SQL Trigger not working correctly
here are the 2 table开发者_JS百科s i have, i want to implement an trigger that customer cannot have more than 5 accounts from a one bank, but can have more than 5 in total.
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),
);
heres the trigger i wrote but i can't create more than 5 accounts in total because it checks for all the accounts in all the banks rather than a single bank.
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
THE PROBLEM IS WITHIN THE GROUPBY FUNCTION AS I GUESS.
this is easy to implement with constraints:
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),
);
Edit: sometimes triggers do not fire. Only trusted constraints 100% guarantee data integrity.
To insert, I would use Numbers table:
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 CUS_NO=@CUS_NO AND BANK_CODE=@BANK_CODE)
I would use a trigger to prohibit modifications of BANK_CODE.
I would try something like this:
Replace this part of your trigger
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
with this:
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
Also consider that the INSERTED table may have multiple records in it. If those records are for more than one customer and any of the customers causes this trigger to rollback the transaction, then the updates for those customers that did not violate your rule will not be applied. This may never happen (if your application never updates records for more than one customer at a time), or may be the intended behavior.
Try this instead of the current query in your trigger. I think that this might work.
My syntax might be a bit off but you get the general idea.
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)
The trouble with your query is that you are only searching by unique customer identifier.
Your query must search a count of a unique customer AND bank identifier together. I'll leave the exact query to you, but here's what you want in pseudocode:
SELECT COUNT(customer_id)
FROM table_name
WHERE customer_id = customer_id_to_validate
AND bank_id = bank_id_to_validate
This will return how many times a customer + bank combination exist. That's the limit you want.
Thanks for the answers, after going through all, i came up with this solution. I inserted a nested query taht will give me the bankcode and by that code i get the count
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
精彩评论