Make a transfer all-or-nothing
A balance transfer changes two rows that must stay consistent. A database transaction groups them into one commit, and any validation failure should roll everything back. SQLite's connection context manager commits on success and rolls back on an exception. Validate the destination as well as the source before treating the operation as complete.
import sqlite3
con = sqlite3.connect(":memory:")
with con:
con.execute("CREATE TABLE sample(x)")Think before coding
The transaction makes both updates one unit. Context-manager rollback protects earlier writes if an exception interrupts the operation. Production concurrency rules and stronger monetary validation should be designed around the chosen database. Work through the example by hand before changing the starter. Decide what should happen for an empty input, a single value and a repeated value where those cases apply. The checks use several inputs so a hard-coded answer cannot stand in for the rule.
Your task
Write transfer(connection, source, target, amount). accounts(id TEXT PRIMARY KEY, balance INTEGER) exists with no pending transaction. Reject amount <= 0, missing accounts, or insufficient funds with ValueError. Move funds atomically, leaving balances unchanged on rejection. A valid same-account transfer is a no-op.
The explanation opens here once every check passes.