2010-09-16 123 views
2

這裏是我擁有的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功能我猜。

回答

1

我會嘗試這樣的事:

這個替換您的觸發

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

0

試試這個,而不是觸發器中的當前查詢。我認爲這可能有效。

我的語法可能有點偏離,但你會得到一般想法。

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) 
0

查詢的麻煩在於您只能通過唯一的客戶標識符進行搜索。

您的查詢必須一起搜索唯一客戶和銀行標識符的計數。我會留下準確的查詢到你,但這裏就是你在僞想要的東西:

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

3

這是很容易與約束來實現:

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

0

感謝您的答案,經歷了所有後,我想出了這個解決方案。我插入一個嵌套查詢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