MariaDB 触发器执行更新,然后在同一个 table 上执行插入

MariaDB trigger to perform an UPDATE and then an INSERT on the same table

我目前有一个 account table 和一个 account_audit table(所有代码都可以在 fiddle here 上找到)。

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

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

因此,在我的审核中插入 2 条记录后 table - 我在两个 table 中都有两条记录,如下所示。

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 无限 - 至少在时间上 tables!

但是,我的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(今天)和今天的新记录 valid_from 到 2038 年的 valid_to(MariaDB 的无穷大?)。

问题是当我运行这个语句

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

account_audittable中的记录变为:

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 而不是名称 - 没有任何效果。我尝试交换旧的。和新的。订单 - 在更新之前或之后尝试 - 我真的疯了!

我如何重写触发器来更新 account_audit table 仅 其帐户所在的人而不是所有帐户 - 也就是说比如,只更新 Bill 的帐户而不更新 Ben 的帐户?

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

Fiddle 是 here.

那是因为你的 where 子句对所有行都是 true

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

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
acct_id | txn_id | acct_name | acct_balance | tax_rate | valid_from | valid_to  
------: | -----: | :-------- | -----------: | -------: | :--------- | :---------
      1 |      1 | Bill      |       100.00 |        0 | 2021-11-07 | 2021-11-07
      2 |      2 | Ben       |      1000.00 |        0 | 2021-11-07 | 2038-01-19
      1 |   null | Bill      |       150.00 |        0 | null       | null      

db<>fiddle here

在我看来,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));