Guided route
Follow the selected readings and build the final output.
This introductory route covers selected foundations, not the entire field.
Finding the next step…
Build a SQLite reading log with keys, joins, constraints and rollback checks.
No SQL background. Use SQLite’s shell without programming, or use Python after Python foundations. You need access to a terminal and a scratch database file.
A reproducible reading-log database with explained queries and a verified rollback.
Start here if the background is new. Equivalent experience is enough.
If you choose the Python workflow, use functions and file handling to build the SQLite reading log.
SQLite developers · reference
Creating a database and basic SQL
Check reading access
Open the readingSQLite developers · reference
Getting started and dot commands
Check reading access
Open the readingPython Software Foundation · reference
Tutorial and SQL placeholders
Check reading access
Open the readingSQLite: SQLite In 5 Minutes Or Less. Run the opening create, insert and select examples in a disposable database.
SQLite: Command Line Shell For SQLite. Open a scratch database; use .tables and .schema to inspect it.
Python reference: sqlite3. Use the tutorial for Python setup; bind user input with placeholders instead of building SQL strings.
SQLite developers · reference
Column definitions and constraints
Check reading access
Open the readingSQLite developers · reference
Single-row and multi-row inserts
Check reading access
Open the readingSQLite developers · reference
Storage classes and type affinity
Check reading access
Open the readingSQLite developers · reference
Introduction and enabling foreign keys
Check reading access
Open the readingSQLite: CREATE TABLE. Define a stable key and a NOT NULL field; test an invalid row.
SQLite: INSERT. Insert a few invented books and explicitly name the columns.
SQLite: Datatypes In SQLite. Compare declared column types with SQLite’s stored values.
SQLite: SQLite Foreign Key Support. Enable PRAGMA foreign_keys=ON for each connection before a transaction; test an orphan row.
Two invented books both have the title “Notes”. Why is the title a poor primary key? Propose a key and explain how a reading entry should refer to its book.
A display name and a stable row identity serve different purposes.
Use a distinct book id as the primary key, allowing titles to repeat. A reading entry stores book_id as a foreign key to books(id). In SQLite, enable foreign-key enforcement for each connection before a transaction, then test that an entry for a missing book is rejected. A title may also change, so it should not be the only identifier used by related records.
What to look for
Common mistake: Assuming a familiar display name is necessarily unique or immutable.
Start this pathway to keep your answers in My learning.
SQLite developers · reference
Simple SELECT, FROM/JOIN, WHERE, ORDER BY and GROUP BY
Check reading access
Open the readingSQLite developers · reference
count(), sum() and avg()
Check reading access
Open the readingSQLite developers · reference
Comparisons, NULL and bound parameters
Check reading access
Open the readingSQLite: SELECT. Predict a query result before running it; follow one joined row.
SQLite: Built-in Aggregate Functions. Compare COUNT(*) and COUNT(column) on a small table with a missing value.
SQLite: SQL Language Expressions. Use IS NULL for missing values and distinguish a value from SQL syntax.
Invented books have ids 1, 2 and 3. Reading entries have ids 10 and 11 for book 1, and id 12 for book 2; book 3 has none. Write a query that returns every book id and its reading-entry count. What counts should it return?
Start from books, preserve unmatched rows and count a reading-entry column.
SELECT books.id, COUNT(readings.id) AS entry_count FROM books LEFT JOIN readings ON readings.book_id = books.id GROUP BY books.id ORDER BY books.id; The result is (1, 2), (2, 1), (3, 0). LEFT JOIN keeps the unmatched book, and COUNT(readings.id) ignores the NULL placeholder for it. COUNT(*) would count that preserved row and incorrectly give the unread book a count of one.
What to look for
Common mistake: Using an inner join that hides unread books or COUNT(*) that counts their preserved row.
Start this pathway to keep your answers in My learning.
SQLite developers · reference
Overview
Check reading access
Open the readingSQLite: UPDATE. Update a copied table and check which rows match before changing them.
SQLite: DELETE. Preview the selected rows before trying a delete in your scratch database.
SQLite: SQLite Online Backup API. Distinguish a consistent backup from copying a database file during active writes.
SQLite developers · reference
BEGIN, COMMIT and ROLLBACK
Check reading access
Open the readingPython Software Foundation · reference
Tutorial and SQL placeholders
Check reading access
Open the readingSQLite: Transaction. Group two related writes and verify that rolling back removes both.
Python reference: sqlite3. Use the tutorial for Python setup; bind user input with placeholders instead of building SQL strings.
In an empty scratch database with the two tables already created, execute BEGIN; insert book id 4; insert a reading for book 4; then execute ROLLBACK. What should remain? How would the result differ with COMMIT?
Both inserts occur inside the same explicit transaction; the tables were created before it.
After ROLLBACK, both tables still exist but neither inserted row remains. The two writes were part of one transaction. Repeating valid inserts in a fresh transaction and using COMMIT preserves both rows. Foreign-key enforcement must already be enabled before BEGIN. Check the state with SELECT rather than assuming an error or rollback had the desired effect.
What to look for
Common mistake: Letting two related writes commit independently and expecting a later rollback to undo both.
Start this pathway to keep your answers in My learning.
Editorial perspectives based on selected works, rather than author-endorsed reading lists.
Follow the selected readings and build the final output.
This introductory route covers selected foundations, not the entire field.
Focus on identities, relationships and rejected invalid states.
Constraints cannot decide whether the information entered is factually true.
Focus on row counts, missing values and a query’s plan.
An efficient query can still answer the wrong question.
Background, different viewpoints, and further reading.
Run the opening create, insert and select examples in a disposable database.
Creating a database and basic SQL
Open a scratch database; use .tables and .schema to inspect it.
Getting started and dot commands
Compare declared column types with SQLite’s stored values.
Storage classes and type affinity
Define a stable key and a NOT NULL field; test an invalid row.
Column definitions and constraints
Insert a few invented books and explicitly name the columns.
Single-row and multi-row inserts
Predict a query result before running it; follow one joined row.
Simple SELECT, FROM/JOIN, WHERE, ORDER BY and GROUP BY
Use IS NULL for missing values and distinguish a value from SQL syntax.
Comparisons, NULL and bound parameters
Compare COUNT(*) and COUNT(column) on a small table with a missing value.
count(), sum() and avg()
Update a copied table and check which rows match before changing them.
Overview and WHERE
Preview the selected rows before trying a delete in your scratch database.
Overview and WHERE
Enable PRAGMA foreign_keys=ON for each connection before a transaction; test an orphan row.
Introduction and enabling foreign keys
Group two related writes and verify that rolling back removes both.
BEGIN, COMMIT and ROLLBACK
Read why a transaction must handle interrupted writes; do not treat this as a recovery guarantee for every setup.
Overview and single-file commit
Compare a lookup with and without a suitable index after the query is correct.
Index term usage
Inspect a query plan; note that its text format can change between releases.
Table and index scans
Create an index for one real lookup and record its cost as well as its benefit.
Overview
Try a schema change on a copy and keep a reproducible migration note.
Adding columns
Name an intermediate query result without introducing recursive SQL yet.
Ordinary common table expressions
Distinguish a consistent backup from copying a database file during active writes.
Overview
Use the tutorial for Python setup; bind user input with placeholders instead of building SQL strings.
Tutorial and SQL placeholders
Compare browser storage with a relational database and explain when the distinction matters.