drop table if exists t;
create table t(account_balance int,earned_amount int);
drop trigger if exists t;
delimiter $$
create trigger t before update on t
for each row
begin
insert into debug_table(msg,msg2) values (old.earned_amount,new.earned_amount);
if new.account_balance > old.account_balance then
set new.earned_amount = new.earned_amount + (new.account_balance - old.Account_balance);
end if;
insert into debug_table(msg,msg2) values (old.earned_amount,new.earned_amount);
end $$
delimiter ;
truncate table t;
truncate table debug_table;
insert into t values (10,10);
update t set account_balance = Account_balance + 10 where 1 = 1;
update t set account_balance = Account_balance - 10 where 1 = 1;
select * from t;
+-----------------+---------------+
| account_balance | earned_amount |
+-----------------+---------------+
| 10 | 20 |
+-----------------+---------------+
1 row in set (0.00 sec)
select * from debug_table;
+----+------+------+
| id | msg | MSG2 |
+----+------+------+
| 1 | 10 | 10 |
| 2 | 10 | 20 |
| 3 | 20 | 20 |
| 4 | 20 | 20 |
+----+------+------+
4 rows in set (0.00 sec)
Note debug_table is not necessary to the solution , it's there to show that the first thing mysql does is write all OLD. values to NEW. values.
Personally I wouldn't store earned_amount, there's to much scope for error, and it can be easily calculated. Imagine for example a positive amount was contrad/reversed that should reduce the earned amount but there is no way of distinguishing this from a real withdrawal.