Learn to protect data integrity with transactions, simplify complex queries with views, and automate database actions with triggers. These three features are the foundation of reliable, maintainable database systems.
A transaction groups multiple SQL statements into a single unit of work. You can commit the whole unit or roll it back as one piece. Start by seeing why this matters.
sqlite3 ecommerce.db "SELECT id, stock_quantity FROM products WHERE id = 1;"sqlite3 ecommerce.db "BEGIN; UPDATE products SET stock_quantity = stock_quantity - 1 WHERE id = 1; INSERT INTO order_items (order_id, product_id, quantity, unit_price) VALUES (1, 1, 1, (SELECT price FROM products WHERE id = 1)); COMMIT;"sqlite3 ecommerce.db "SELECT id, stock_quantity FROM products WHERE id = 1;"When a customer buys a product, two things must happen together: (1) reduce stock and (2) add the order item. If the stock update succeeds but the order item insert fails (maybe invalid order_id), you've lost inventory with no record of where it went. BEGIN starts an explicit transaction and COMMIT makes the whole unit permanent. If one statement fails before COMMIT, SQLite stops at the failing statement and leaves the transaction open so your application can decide whether to fix the problem or issue ROLLBACK. In well-written application code, a failure in a multi-step unit should trigger ROLLBACK so none of the partial work is kept. That is atomicity — the 'A' in ACID.
First query shows the product's original stock quantity. After the transaction, stock_quantity is reduced by 1 and a new order_item row exists. Both changes happened together.