The execution unit
Every SQL statement runs through a cursor. conn.execute(sql, params) returns one (a fresh cursor each call). You read rows from it via:
cursor.fetchone()— next row as a tuple, or None.cursor.fetchmany(n)— up to n rows as a list of tuples.cursor.fetchall()— all remaining rows as a list (caution: can be huge).- Iteration —
for row in cursor:streams rows lazily; idiomatic for large result sets.
Tip: Default to iteration.
fetchall() on a million-row query allocates a million tuples in memory; the iterator streams them one at a time.