All 40 lessons
Lesson 34 of 40 · Creating & Changing Data
SQL Transactions
By Skillancy Editorial Team
Every example runs on the ShopKart dataset, already loaded in the free SQL Compiler. Click Try it in the SQL Compiler under a query to open it there, then press Run.
A transaction groups several SQL statements so they succeed or fail as one unit. Placing an order touches several tables: create the order, add its items, reduce stock. If the system fails halfway, you don't want an order without items or stock that dropped for nothing. Transactions guarantee all or nothing.
Syntax
BEGIN; -- start the transaction
statement 1;
statement 2;
COMMIT; -- save everything
-- or
ROLLBACK; -- undo everything since BEGINACID
| Property | Meaning | ShopKart example |
|---|---|---|
| Atomicity | all statements happen, or none do | order and stock update are saved together |
| Consistency | constraints are never broken | stock can't go negative if a CHECK forbids it |
| Isolation | concurrent transactions don't see each other's half-done work | two shoppers buying the last TV don't both succeed |
| Durability | committed data survives a crash | a confirmed order is still there after a restart |
Examples
1. COMMIT: place an order
BEGIN;
INSERT INTO orders (order_id, customer_id, order_date, status, payment_method)
VALUES (1025, 2, '2026-02-15', 'Pending', 'UPI');
INSERT INTO order_items (order_item_id, order_id, product_id, quantity, unit_price)
VALUES (39, 1025, 103, 1, 31990.00);
UPDATE products SET stock_qty = stock_qty - 1 WHERE product_id = 103;
COMMIT;
SELECT o.order_id, oi.product_id, p.stock_qty
FROM orders o
JOIN order_items oi ON oi.order_id = o.order_id
JOIN products p ON p.product_id = oi.product_id
WHERE o.order_id = 1025;Try it in the SQL CompilerResult:
| order_id | product_id | stock_qty |
|---|---|---|
| 1025 | 103 | 11 |
(1 row)
All three changes were saved together. Stock fell from 12 to 11.
2. ROLLBACK: undo a mistake
Someone runs a price update without a WHERE clause, inside a transaction:
BEGIN;
UPDATE products SET price = 0; -- oops: every product
SELECT COUNT(*) AS free_products FROM products WHERE price = 0;Try it in the SQL CompilerResult:
| free_products |
|---|
| 15 |
(1 row)
Every product is now free, but only inside this transaction. Roll it back:
ROLLBACK;
SELECT COUNT(*) AS free_products FROM products WHERE price = 0;Try it in the SQL CompilerResult:
| free_products |
|---|
| 0 |
(1 row)
Nothing changed. This is why experienced analysts run manual UPDATE and DELETE statements inside BEGIN ... ROLLBACK/COMMIT.
3. Errors cancel the whole transaction
Add a rule that stock can't go negative, then try to sell more than we have:
ALTER TABLE products ADD CONSTRAINT chk_stock CHECK (stock_qty >= 0);Try it in the SQL CompilerResult:
Query OK, 0 row(s) affected.
BEGIN;
INSERT INTO orders (order_id, customer_id, order_date, status, payment_method)
VALUES (1026, 5, '2026-02-16', 'Pending', 'Card');
UPDATE products SET stock_qty = stock_qty - 50 WHERE product_id = 115; -- only 20 in stock
COMMIT;Error: new row for relation "products" violates check constraint "chk_stock"
The UPDATE failed, so PostgreSQL marks the transaction as failed and discards everything when it ends. End it with ROLLBACK, then check that order 1026 was never created:
ROLLBACK;
SELECT COUNT(*) AS order_1026_rows FROM orders WHERE order_id = 1026;Try it in the SQL CompilerResult:
| order_1026_rows |
|---|
| 0 |
(1 row)
4. SAVEPOINT: partial rollback
A savepoint marks a point you can roll back to without losing earlier work:
BEGIN;
UPDATE products SET stock_qty = stock_qty + 100 WHERE product_id = 108; -- restock bottles
SAVEPOINT after_restock;
UPDATE products SET stock_qty = 0 WHERE product_id = 110; -- mistake
ROLLBACK TO SAVEPOINT after_restock; -- undo only the mistake
COMMIT;
SELECT product_id, stock_qty FROM products WHERE product_id IN (108, 110);Try it in the SQL CompilerResult:
| product_id | stock_qty |
|---|---|
| 108 | 400 |
| 110 | 500 |
(2 rows)
The restock was kept (300 → 400) and the mistake was undone (face wash still at 500).
Common mistakes
- Forgetting COMMIT. Changes stay invisible to others, and locks are held until the session ends.
- Long-running transactions. Holding a transaction open for minutes blocks other users and grows logs. Keep them short.
- Assuming DDL can always be rolled back. PostgreSQL can roll back
CREATE/ALTER/DROP; MySQL and Oracle commit DDL immediately.
Practice question
In one transaction, move 10 units of stock from the Prestige cooker (107) to a new "Display Unit" count by reducing its stock by 10, then decide it was a mistake and undo it. Confirm the stock is unchanged.
Show solution
BEGIN;
UPDATE products SET stock_qty = stock_qty - 10 WHERE product_id = 107;
ROLLBACK;
SELECT product_id, stock_qty FROM products WHERE product_id = 107;Try it in the SQL CompilerResult:
| product_id | stock_qty |
|---|---|
| 107 | 45 |
(1 row)
Key takeaways
- A transaction is all or nothing:
BEGIN, thenCOMMITorROLLBACK. - ACID = atomicity, consistency, isolation, durability.
- An error inside a transaction means none of its changes are saved.
- Run risky manual changes inside a transaction so you can roll them back.
Frequently asked questions
What is a transaction in SQL?
A group of statements that succeed or fail together. Either all changes are saved with COMMIT, or none are, with ROLLBACK.
What does ACID stand for?
Atomicity (all or nothing), Consistency (rules and constraints always hold), Isolation (concurrent transactions don't interfere) and Durability (committed changes survive crashes).
Are single statements transactions too?
Yes. In autocommit mode, which is the default in most tools, each statement runs as its own transaction and is committed automatically when it succeeds.
Keep learning SQL
One email a week with SQL and analytics guides, new practice questions and cohort dates. No spam, unsubscribe anytime.
Prefer a one-page summary? Download the free SQL cheat sheet (PDF)