SQL 触发器无法正常工作

发布于 2024-09-19 22:16:39 字数 959 浏览 5 评论 0原文

这是我拥有的 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

据我猜测,问题出在 GRUBBY 函数内。

here are the 2 tables 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦里兽 2024-09-26 22:16:39

这很容易在有约束的情况下实现:

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。

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.

剧终人散尽 2024-09-26 22:16:39

我会尝试这样的操作:

将触发器的这一部分替换

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 表中可能有多个记录。如果这些记录适用于多个客户,并且任何客户导致此触发器回滚事务,则不会应用那些未违反您的规则的客户的更新。这可能永远不会发生(如果您的应用程序从不一次更新多个客户的记录),或者可能是预期的行为。

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.

偏爱你一生 2024-09-26 22:16:39

尝试此操作而不是触发器中的当前查询。我认为这可能有效。

我的语法可能有点偏差,但你已经了解了总体思路。

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) 

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) 
故人如初 2024-09-26 22:16:39

您的查询的问题在于您仅通过唯一的客户标识符进行搜索。

您的查询必须同时搜索唯一客户和银行标识符的计数。我将把确切的查询留给您,但这就是您想要的伪代码:

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

这将返回客户+银行组合存在的次数。这就是你想要的极限。

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.

木緿 2024-09-26 22:16:39

感谢您的回答,在经历了所有这些之后,我想出了这个解决方案。我插入了一个嵌套查询,它会给我银行代码,通过该代码我可以得到计数

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文