PyComplete Python Course
Advanced 55 min

Module 20 β€” Python + SQL

Storing data permanently and querying it with SQLite, straight from Python.

Prerequisite: Module 19 β€” Python Projects

After this lesson, you will be able to

  • Connect to a SQLite database from Python and create a table
  • Insert, select, update, and delete records using SQL
  • Build a simple CRUD (Create, Read, Update, Delete) workflow

Concept & Syntax

Files are fine for small amounts of data, but once you need to search, filter, sort, or reliably update records, a database is the right tool. SQL (Structured Query Language) is the language used to talk to relational databases. SQLite is a lightweight, file-based database engine built into Python's standard library via the sqlite3 module β€” no separate server required, which makes it perfect for learning and for small applications.

Syntax
import sqlite3
conn = sqlite3.connect("app.db")
cursor = conn.cursor()
cursor.execute("SELECT * FROM students WHERE grade > ?", (80,))
conn.commit()
conn.close()

Examples

Connecting and creating a table Very Easy

Connecting and creating a table
import sqlite3
 
conn = sqlite3.connect("school.db")
cursor = conn.cursor()
cursor.execute("""
    CREATE TABLE IF NOT EXISTS students (
        id INTEGER PRIMARY KEY,
        name TEXT,
        grade INTEGER
    )
""")
conn.commit()
conn.close()
Output(creates school.db with an empty students table β€” no console output)

connect() opens (or creates) the database file. IF NOT EXISTS prevents an error if the table is already there. commit() saves the change to disk.

Inserting records safely Easy

Inserting records safely
import sqlite3
 
conn = sqlite3.connect("school.db")
cursor = conn.cursor()
cursor.execute("INSERT INTO students (name, grade) VALUES (?, ?)", ("Ada", 92))
conn.commit()
conn.close()
Output(adds one row to the students table)

The ? placeholders are filled in safely from the tuple β€” always do this instead of building SQL strings with +, which opens the door to SQL injection bugs.

Selecting with WHERE and ORDER BY Intermediate

Selecting with WHERE and ORDER BY
import sqlite3
 
conn = sqlite3.connect("school.db")
cursor = conn.cursor()
cursor.execute("SELECT name, grade FROM students WHERE grade > ? ORDER BY grade DESC", (80,))
for row in cursor.fetchall():
    print(row)
conn.close()
Output('Ada', 92)

WHERE filters rows; ORDER BY grade DESC sorts results from highest to lowest grade. fetchall() returns every matching row as a list of tuples.

Updating and deleting Real World

Updating and deleting
import sqlite3
 
conn = sqlite3.connect("school.db")
cursor = conn.cursor()
cursor.execute("UPDATE students SET grade = ? WHERE name = ?", (95, "Ada"))
cursor.execute("DELETE FROM students WHERE grade < ?", (50,))
conn.commit()
conn.close()
Output(updates Ada's grade, removes any student below 50 β€” no console output)

UPDATE changes existing rows matching WHERE; DELETE removes rows matching WHERE. Both need commit() to actually save.

Visual Explanation

sqlite3.connect("app.db")cursor = conn.cursor()cursor.execute("SELECT / INSERT / UPDATE / DELETE ...")conn.commit() ← saves changes to diskconn.close()
The typical lifecycle of any Python + SQLite operation.
πŸ’‘ Why does this work?

Read the concept explanation above again slowly, line by line β€” every keyword there maps directly onto a line of code in the examples. If it still doesn't click, re-run the traced example (if this lesson has one) one step at a time.

πŸ” What happens internally? (advanced)

Under the hood, Python compiles your source into bytecode and runs it on a virtual machine (the CPython interpreter). Variables are names in a namespace dictionary pointing at objects in memory β€” which is exactly what the memory panel in the tracer above is showing you.

Common Mistakes

βœ— Common mistake 1

Building SQL strings by directly inserting user input opens a serious security hole called SQL injection.

βœ— Avoid this
This raises not a Python error, but a real security vulnerability
name = input("Name: ")
cursor.execute(f"SELECT * FROM students WHERE name = '{name}'")
βœ“ Better approach
Fixed
name = input("Name: ")
cursor.execute("SELECT * FROM students WHERE name = ?", (name,))
βœ— Common mistake 2

Forgetting conn.commit() means INSERT/UPDATE/DELETE changes are lost when the connection closes.

βœ— Avoid this
This raises no crash, but the data silently never gets saved
cursor.execute("INSERT INTO students (name, grade) VALUES (?, ?)", ("Sam", 88))
conn.close()  # forgot commit β€” the insert is lost!
βœ“ Better approach
Fixed
cursor.execute("INSERT INTO students (name, grade) VALUES (?, ?)", ("Sam", 88))
conn.commit()
conn.close()
βœ“ Best practices
  • Always use ? placeholders for values in a query β€” never build SQL with string formatting.
  • Call conn.commit() after any INSERT, UPDATE, or DELETE.
  • Close the connection (or use a with block) once you're done with the database.
  • Use CREATE TABLE IF NOT EXISTS so setup code can safely run more than once.

Exercise & Challenge

Exercise 1 β€” Fill in the blank

Given this code
cursor.execute(____________________, (100,))

Complete the execute() call to safely select all students with a grade of exactly 100, using a placeholder rather than string formatting.

πŸ† Challenge

Build a tiny CRUD script for a 'books' table (id, title, author) that creates the table, inserts two books, then selects and prints every book ordered by title.

  • Use CREATE TABLE IF NOT EXISTS
  • Insert at least 2 rows using ? placeholders
  • SELECT with ORDER BY title, and print each row
πŸ’‘ Need a hint?

cursor.execute("SELECT * FROM books ORDER BY title")

πŸ” Show a sample solution
Python
import sqlite3
 
conn = sqlite3.connect("library.db")
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS books (id INTEGER PRIMARY KEY, title TEXT, author TEXT)")
cursor.execute("INSERT INTO books (title, author) VALUES (?, ?)", ("Dune", "Herbert"))
cursor.execute("INSERT INTO books (title, author) VALUES (?, ?)", ("Emma", "Austen"))
conn.commit()
cursor.execute("SELECT * FROM books ORDER BY title")
for row in cursor.fetchall():
    print(row)
conn.close()

Quiz

Answer every question, then submit to see your score and explanations.

1. What module does Python's standard library provide for SQLite?

sql
sqlite3
db
pysql
sqlite3 is built into Python's standard library β€” no installation needed.

2. Why should you use ? placeholders instead of building SQL with f-strings?

Placeholders are shorter to type
It prevents SQL injection vulnerabilities
f-strings don't work with SQL at all
There's no real reason
Placeholders let the database driver safely escape values, closing off SQL injection attacks.

3. What must you call after an INSERT/UPDATE/DELETE to actually save the change?

conn.save()
conn.commit()
cursor.finish()
Nothing, it saves automatically
commit() writes the transaction to disk β€” without it, changes can be lost.

4. What does WHERE grade > 80 ORDER BY grade DESC do?

Sorts ascending, no filter
Filters grades above 80, sorted highest to lowest
Deletes rows below 80
Selects only 80 exactly
WHERE filters rows; ORDER BY ... DESC sorts them from highest to lowest.

Summary

  • sqlite3 connects Python to a lightweight, file-based SQL database with no separate server.
  • Use ? placeholders for values β€” never build SQL strings with user input directly.
  • commit() saves INSERT/UPDATE/DELETE changes; without it, they can be lost.
  • WHERE filters rows and ORDER BY sorts them β€” the foundation of every useful query.

Related lessons

Saved privately in your browser β€” no account needed.