import sqlite3 con = sqlite3.connect("app.db")★Opens (or creates) a database file. Use":memory:"for a throwaway in-RAM DB — ideal for tests.cur = con.cursor() cur.execute("SELECT 1"); cur.fetchone()★A cursor runs statements and holds results. Or skip it:con.execute(...)is a shortcut that returns a temporary cursor.con = sqlite3.connect("file:app.db?mode=ro", uri=True)URI filenames unlock options like read-only (mode=ro) and shared cache.con.close() # release the file handle★Always close when done. Note:with con:does NOT close (card 5) — it's a transaction block.
cur.execute("SELECT * FROM user WHERE id = ?", (uid,))★qmark placeholders. Pass a tuple of values — even for one, note the trailing comma(uid,). SQLite substitutes safely.cur.execute("... WHERE name = :name", {"name": n})★Named placeholders take a dict — clearer for many params.cur.executescript(""" CREATE TABLE t(id INTEGER PRIMARY KEY, name TEXT); CREATE INDEX ix ON t(name); """)Run multiple statements at once (schema setup). Note:executescriptissues an implicit COMMIT first.# NEVER: f-strings / .format / % into SQL — injection cur.execute(f"... WHERE id = {uid}") # WRONGString-building SQL is an injection hole. Always use?/named params for values.
row = cur.fetchone() # one tuple or None rows = cur.fetchall() # list of tuples some = cur.fetchmany(100)★Pull results after anexecute.fetchonereturnsNonewhen exhausted.for row in cur.execute("SELECT id, name FROM user"): ... # iterate lazily, memory-friendly★A cursor is iterable — the idiomatic way to stream rows without loading all of them.con.row_factory = sqlite3.Row row = con.execute("SELECT * FROM user").fetchone() row["name"] · row.keys()★Access columns by name (and still by index).sqlite3.Rowis the go-to row factory; set a plaindictfactory for JSON output.