mysql - 如何根据先前的值更新列?

标签 mysql sql database-trigger

我在这里阅读了很多答案,但无法适应我的需求。

我想在下面的表格中更新 BALANCE 列:

余额 = 旧余额 + 新金额

+----+----------------+---------+------------+-------------+---------------------+------------------+--------+----------+---------+
| ID | TRANSACTION_ID | BANK_ID | ACCOUNT_ID | CUSTOMER_ID | CREATED             | DESCRIPTION      | AMOUNT | CURRENCY | BALANCE |
+----+----------------+---------+------------+-------------+---------------------+------------------+--------+----------+---------+
|  1 | T1             |       2 |          2 |           1 | 2018-04-22 00:00:00 | TRANSACTION TEST | 100.00 | GBP      |    NULL |
|  2 | T2             |       2 |          2 |           1 | 2018-04-22 00:00:00 | TRANSACTION TEST | 125.00 | GBP      |    NULL |
|  3 | T3             |       2 |          2 |           1 | 2018-04-22 00:00:00 | TRANSACTION TEST | -73.00 | GBP      |    NULL |
+----+----------------+---------+------------+-------------+---------------------+------------------+--------+----------+---------+

这是我想要的结果,如下所示: 我让它执行:

SET @balance:=0;
UPDATE TRANSACTIONS SET BALANCE = (@balance := @balance + AMOUNT) WHERE ID > 0;

插入新列后无法触发上面的语句吗?

+----+----------------+---------+------------+-------------+---------------------+------------------+--------+----------+---------+
| ID | TRANSACTION_ID | BANK_ID | ACCOUNT_ID | CUSTOMER_ID | CREATED             | DESCRIPTION      | AMOUNT | CURRENCY | BALANCE |
+----+----------------+---------+------------+-------------+---------------------+------------------+--------+----------+---------+
|  1 | T1             |       2 |          2 |           1 | 2018-04-22 00:00:00 | TRANSACTION TEST | 100.00 | GBP      |  100.00 |
|  2 | T2             |       2 |          2 |           1 | 2018-04-22 00:00:00 | TRANSACTION TEST | 125.00 | GBP      |  225.00 |
|  3 | T3             |       2 |          2 |           1 | 2018-04-22 00:00:00 | TRANSACTION TEST | -73.00 | GBP      |  152.00 |
+----+----------------+---------+------------+-------------+---------------------+------------------+--------+----------+---------+

我尝试使用触发器:

DELIMITER $$ 
CREATE TRIGGER updateBalance AFTER INSERT ON TRANSACTIONS 
FOR EACH ROW 
BEGIN
    SET NEW.BALANCE = BALANCE + NEW.AMOUNT;
END $$ 
DELIMITER ;

我得到了错误:

错误代码:1362。触发器后不允许更新新行

我是 SQL 和 MySQL 新手,我相信这是高级用户的常见任务。

最佳答案

不应具体化可以从其他(具体化)值计算得出的值,因为这可能会导致不一致。

将列全部删除。

ALTER TABLE transactions
            DROP balance;

并创建一个 View :

CREATE VIEW transactions_with_balance
AS
SELECT t1.*,
       (SELECT sum(t2.amount)
               FROM transactions t2
               WHERE t2.bank_id = t1.bank_id
                     AND t2.account_id = t1.account_id
                     AND t2.id <= t1.id) balance
       FROM transactions t1;

db<>fiddle

如果您使用的是 MySQL 版本 8 或更高版本,您还可以将子查询替换为窗口版本的 sum()

CREATE VIEW transactions_with_balance
AS
SELECT t1.*,
       sum(amount) OVER (PARTITION BY t1.bank_id,
                                      t1.account_id
                         ORDER BY t1.id) balance
       FROM transactions t1;

db<>fiddle

customer_id在表中似乎也放错了位置,因为我认为有一个帐户表,其中帐户所属的客户存储在客户表的外键中。因此您可以通过 account_id 获取客户。

关于mysql - 如何根据先前的值更新列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55875356/

相关文章:

mysql - 更改 mysql 查询输出中的特定字段

mysql GROUP BY 就一个 View 确实很慢

sql - 如何在 sql 中添加外部表中的其他列?

sql - 如何在 WHERE 子句中编写带有 SELECT 语句的 SQL DELETE 语句?

ubuntu下Mysql无法重启

mysql - 当我在本地主机上运行我的服务器时出现问题(ruby on rails)

sql - 使用联接和匹配特定列执行 SQL 更新

包含创建日期的所有表的 Postgresql 触发器

oracle - "after servererror on database trigger"是个好主意吗?

sql - 如何在该触发器中找到已调用触发器的 sql 语句的 audsid、sql_id