最近在做相关账户资金存储的设计,希望能对余额进行实时的存储,同意能够快速地查询到相应账户的当前账户余额。没有做过财务相关的开发设计,因此战术想了很久,简单把思考过程写一下。做参考,也欢迎专业人士指正。
设计需求
- 存储收支流水
- 显示每笔流水当前的余额情况
- 查询对应账户当前余额
原始数据表
t_jounal
id | user_id | price | type |
---|---|---|---|
1 | 0001 | 1000 | in |
2 | 0001 | -300 | out |
3 | 0002 | 2000 | in |
4 | 0001 | 1300 | in |
5 | 0003 | -400 | out |
最开始的思路是直接写视图查询出相关的数据
select user_id,sum(price) from t_jounal group by user_id;
这样做比较快,可以实时算出当前账户余额,但是不好在流水上对每笔流水目前的余额情况进行表示。
之前问题在银行工作的同事,余额的设计是不是在每一部分都需要同步存储,他们给的答复是在每次操作
都会对当前的余额情况进行一次存储。因此接下来就在想怎么将余额进行同步存储。这个Excel特别好做。
开始想着直接写存储过程,但是这个应用都是进行批处理,方案不好,还是直接通过insert语句进行插入:
- 在表中添加余额列(如下表)
t_jounal
id | user_id | price | balance | type |
---|---|---|---|---|
1 | 0001 | 1000 | 1000 | in |
2 | 0001 | -300 | 700 | out |
3 | 0002 | 2000 | 2000 | in |
4 | 0001 | 1300 | 2000 | in |
5 | 0003 | -400 | -400 | out |
- 查询到上一条记录的余额,并与本次插入的金额进行求和,算出本次的余额
插入数据{user_id:"0001",price:"300",type:"in"}
insert into t_jounal(user_id,price,balance,type) values(0001,300,300+(select balance from t_jounal where id=max(id) and user_id=0001));
SQL语句有问题,我写的数据库里只是单用户,因此可以直接通过自增的ID进行判断取最近的一条记录进行处理
从这里也看出来其中有很多问题,另外一点,如果是插入的第一条记录,那会出现插入错误的情况。写了
好久都存在一定的问题,最后放弃了。最后,想到了用触发器来解决这个问题。
首先建立一个表对每一个账户进行余额存储,满足查询当前余额的问题,同时,使用触发器,在每次进行
流水插入的时候,通过账户余额表中的余额加上插入金额进行计算,算出当前流水余额,同时更新流水以及余额表。
t_balance
id | balance |
---|---|
0001 | 0 |
CREATE DEFINER=`root`@`localhost` TRIGGER `db`.`t_jounal_before_INSERT` before INSERT ON `t_jounal` FOR EACH ROW
BEGIN
set NEW.balance = NEW.price + (select balance from t_balance where id = NEW.user_id);
update t_balance set balance = NEW.balance where id = NEW.user_id;
END
基本解决问题,可以进行同步更新,注意由于对插入的行进行了字段的更新,因此要使用before的insert