【问题标题】:MariaDB trigger to perform an UPDATE and then an INSERT on the same tableMariaDB 触发器在同一张表上执行 UPDATE 和 INSERT
【发布时间】:2021-12-20 17:43:36
【问题描述】:

我目前有一个account 表和一个account_audit 表(所有代码都可以在小提琴here 上找到)。

我有两个触发器,它们根据插入到帐户表中的数据将记录插入到 account_audit 表中。

1 触发器是一个 ON INSERT 触发器,它只插入这些值 - 工作正常。

所以,在我的审计表上插入 2 条记录后 - 我在两个表中都有两条记录,如下所示。

SELECT * FROM account;

给予

acct_id acct_name   acct_balance    tax_rate    acct_opened
      1 Bill            100.00          0.10     2019-11-01
      2 Ben            1000.00          0.10     2019-11-01

SELECT * FROM account_audit;

给予

acct_id txn_id  acct_name   acct_balance    tax_rate    valid_from  valid_to
      1      1       Bill         100.00        0.10    2021-11-07  2038-01-19
      2      2        Ben        1000.00        0.10    2021-11-07  2038-01-19

一切都好 - 2038 年是 MariaDB 无穷大 - 至少在临时表中!

但是,我的UPDATE触发器如下:

CREATE TRIGGER testtrigger_upd 
AFTER UPDATE ON account
  FOR EACH ROW BEGIN
    UPDATE account_audit SET valid_to = NOW() 
    WHERE ((valid_to = '2038-01-19') AND (OLD.acct_name = NEW.acct_name));
    INSERT INTO 
      account_audit (acct_id, acct_name, acct_balance, tax_rate) 
      VALUES 
      (
        OLD.acct_id, 
        OLD.acct_name, 
        NEW.acct_balance, 
        OLD.tax_rate
        
        -- valid_from - NOW()!
        -- valid_to DEFAULTs to '2038-01-19' which is what we want for updates to balance 
      );
END;

因此,当我更新帐户余额时,我希望 account_audit 跟踪反映这一点,然后将最新(插入之前)余额记录转到 valid_to(今天)和新记录 @987654331 @ 今天到 valid_to 在 2038 年(MariaDB 无限?)。

问题是当我运行这个语句时

UPDATE account 
SET acct_balance = acct_balance + 50 WHERE acct_name = 'Bill';  -- name is UNIQUE

account_audit 表中的记录变为:

acct_id txn_id  acct_name   acct_balance    tax_rate    valid_from  valid_to
      1      1       Bill         100.00    0.10        2021-11-07  2021-11-07
      1      3       Bill         150.00    0.10        2021-11-07  2038-01-19
      2      2        Ben        1000.00    0.10        2021-11-07  2021-11-07

您可以看到 Bill 的记录已插入,但问题是 Ben 的记录也已更新为今天插入的日期 - 我显然只希望 Bill 发生这种情况!

我的触发器中有WHERE ((valid_to = '2038-01-19') AND (OLD.acct_name = NEW.acct_name));,我尝试了很多其他方法-WHERE OLD.acct_id = NEW.acct_id,我尝试将更新更改为使用acct_id 而不是名称-没有任何效果。我尝试交换OLD。和新的。订购 - 在更新之前或之后尝试 - 我真的疯了!

如何重写触发器以更新其帐户的人而不是所有帐户的 account_audit 表 - 也就是说,仅更新 Bill 的帐户而不是 Ben 的帐户? p>

我知道临时表功能 - 我不想使用它,因为这是为了研究,我必须使用触发器!

小提琴是here

【问题讨论】:

    标签: mysql sql triggers mariadb mariadb-10.5


    【解决方案1】:

    那是因为您的 where 子句适用于所有行

    因此更改更新查询以检查表

    CREATE TRIGGER testtrigger_upd 
    AFTER UPDATE ON account
      FOR EACH ROW BEGIN
        UPDATE account_audit SET valid_to = NOW() 
        WHERE ((valid_to = '2038-01-19') AND (acct_name = NEW.acct_name));
        INSERT INTO 
          account_audit (acct_id, acct_name, acct_balance, tax_rate) 
          VALUES 
          (
            OLD.acct_id, 
            OLD.acct_name, 
            NEW.acct_balance, 
            OLD.tax_rate
            
            -- valid_from - NOW()!
            -- valid_to DEFAULTs to '2038-01-19' which is what we want for updates to balance 
          );
    END;
    
    UPDATE account 
    SET acct_balance = acct_balance + 50 WHERE acct_name = 'Bill';
    
    SELECT * FROM account_audit
    
    帐户 ID | txn_id |账户名 |账户余额 |税率 |有效来自 |有效 ------: | -----: | :-------- | ------------: | --------: | :--------- | :--------- 1 | 1 |比尔 | 100.00 | 0 | 2021-11-07 | 2021-11-07 2 | 2 |本 | 1000.00 | 0 | 2021-11-07 | 2038-01-19 1 | |比尔 | 150.00 | 0 | |

    db小提琴here

    【讨论】:

      【解决方案2】:

      在我看来,where 子句

      WHERE ((valid_to = '2038-01-19') AND (OLD.acct_name = NEW.acct_name));

      对 Ben 和 Bill 都有效。所以它会为他们两个更新。

      一种解决方案可能是将其稍微更改为:

      WHERE ((valid_to = '2038-01-19') AND (acct_name = OLD.acct_name));

      【讨论】:

      • WHERE ((valid_to = '2038-01-19') AND (acct_name = OLD.acct_name)); - 那got it!如果您愿意将其写下来,我会很乐意将其标记为正确并投赞成票。简单的错误,但我是 MySQL/MariaDB 触发器的初学者...
      • 非常感谢!我现在已经更新了。这是一个很好的问题。当您身处险境时,很难透过树木看到森林。
      • 我将您的答案标记为正确 - 也尝试过投票 - 没有 15 个代表。然而,但它说我的投票被记录了 - 所以希望你能得到更多的分数!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-21
      • 1970-01-01
      相关资源
      最近更新 更多