SQLite with Python's sqlite3
SQLite is the world's most-deployed database — it's in every phone, every browser, every OS. And Python ships sqlite3 in the standard library.
Why start here
- No server — just a file (or
:memory:). - Real SQL — everything you learn transfers to Postgres / MySQL.
- Great for local dev + testing — a real Postgres app can use SQLite in unit tests.
- Ships with Python — no install, works in Pyodide.
The API you'll use 90% of the time
sqlite3.connect(path)— opens the file (creates if missing).conn.cursor()— where you run queries.cur.execute(sql, params)— always pass params separately.cur.executemany(sql, list_of_tuples)— batch insert.conn.commit()— writes are transactional; must commit.row_factory = sqlite3.Row— get dict-like rows.
SQL injection: the one rule
# WRONG — turns user input into code
cur.execute(f"SELECT * FROM users WHERE email = '{email}'")
# RIGHT — driver handles escaping
cur.execute("SELECT * FROM users WHERE email = ?", (email,))
This is the #1 web vulnerability year after year. Don't be a statistic.
Try it
- Add a
bio TEXTcolumn and populate it. - Query all users who joined after
'2026-01-01'.
3 graded exercises
Write the code, click Check. We’ll tell you exactly what to fix.
- Exercise 1
Create a
userstable with columnsid INTEGER PRIMARY KEYandemail TEXT, insert one row with emailalice@example.comusing a parametrized query, then SELECT and print the email. - Exercise 2
The
userstable is pre-populated. Write a parametrized SELECT that finds the row where email isbob@example.comand prints just that user'sid. Never build SQL with f-strings — use a?placeholder. - Exercise 3
Using
SELECT COUNT(*) FROM users, print the number of users doubled (i.e. count times 2). The table has 3 users, so expected output is6.