问题
I have an Android application that helps the user keep track of their finances. The application has a database that stores account and transaction information. Each time a transaction is recorded I also have to update the account table to adjust that account's balance, as well as it's remaining allowance for a certain spending period. The accounts table looks like this:
| id | name | balance | allowance | allowanceRemaining | spendingPeriod |
And a transaction table that looks like this:
| id | description | amount | withdrawal | discretionary | accountID |
Withdrawal and discretionary are both integers that are 0 or 1 to act as booleans. I have tried the following to at least set the balance based on if a transaction was a withdrawal or not but I am getting syntax errors and I can't figure out why. Even beyond syntax, though, I am having trouble understanding the logic and created the proper case statements.
CREATE TRIGGER update_account AFTER INSERT ON transactions
BEGIN
UPDATE accounts a SET a.balance =
(CASE WHEN new.withdrawal = 1 THEN a.balance - new.amount ELSE
a.balance + new.amount END) WHERE a.id = new.accountID;
END;
In pseudocode, what I would like to do is:
- If the transaction is a deposit, add the money
- If the transaction is a withdrawal, check if it is discretionary
- If it is discretionary, remove from the balance and the allowance remaining
- If it is not, remove only from the balance.
I made an SQL Fiddle, that has some quick sample data but no trigger.
回答1:
UPDATE wants the new value for each changed column, so you have to formulate your requirements this way:
The balance
- increases by the amount for a deposit,
- decreases by the amount for a withdrawal.
The remaining allowance
- decreases by the amount for a discetionary withdrawal.
As for the syntax, you cannot use an alias for the UPDATEd table:
CREATE TRIGGER update_account
AFTER INSERT ON transactions
BEGIN
UPDATE accounts
SET balance = CASE
WHEN new.withdrawal THEN balance - new.amount
ELSE balance + new.amount
END,
allowanceRemaining = CASE
WHEN new.withdrawal AND new.discretionary
THEN allowanceRemaining - new.amount
ELSE allowanceRemaining
END
WHERE id = NEW.accountID;
END;
It might be simpler to use the WHEN clause of the trigger:
CREATE TRIGGER update_balance_for_deposit
AFTER INSERT ON transactions
WHEN NOT NEW.withdrawal
BEGIN
UPDATE accounts
SET balance = balance + NEW.amount
WHERE id = NEW.accountID;
END;
CREATE TRIGGER update_balance_for_withdrawal
AFTER INSERT ON transactions
WHEN NEW.withdrawal
BEGIN
UPDATE accounts
SET balance = balance - NEW.amount
WHERE id = NEW.accountID;
END;
CREATE TRIGGER update_allowance_for_discretionary_withdrawal
AFTER INSERT ON transactions
WHEN NEW.withdrawal AND NEW.discretionary
BEGIN
UPDATE accounts
SET allowanceRemaining = allowanceRemaining - NEW.amount
WHERE id = NEW.accountID;
END;
来源:https://stackoverflow.com/questions/27372310/creating-an-sqlite-trigger-that-updates-bank-account-based-on-transaction-inform