这是我拥有的2个表,我想实现一个触发器,客户不能拥有一个银行超过5个帐户,但总共可以超过5个。
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
问题出现在我认为的GROUPBY功能中。
答案 0 :(得分: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%保证数据的完整性。
要插入,我会使用Numbers表:
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)
我会使用触发器禁止修改BANK_CODE。
答案 1 :(得分: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
还要考虑INSERTED表中可能有多个记录。如果这些记录针对多个客户,并且任何客户导致此触发器回滚事务,则不会应用那些未违反规则的客户的更新。这可能永远不会发生(如果您的应用程序永远不会一次更新多个客户的记录),或者可能是预期的行为。
答案 2 :(得分: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)
答案 3 :(得分:0)
您查询的问题在于您只按唯一客户标识符进行搜索。
您的查询必须一起搜索唯一客户和银行标识符的计数。我会将确切的查询留给您,但这是您想要的伪代码:
SELECT COUNT(customer_id)
FROM table_name
WHERE customer_id = customer_id_to_validate
AND bank_id = bank_id_to_validate
这将返回客户+银行组合存在的次数。这是你想要的限制。
答案 4 :(得分:0)
感谢您的答案,经过一切,我想出了这个解决方案。我插入了一个嵌套查询,它将为我提供银行代码,并通过该代码获取计数
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