Pass values as a tuple to ?. Never build SQL with an f-string from user text.
Goal
Select Nairobi with a placeholder, then show why string concat is unsafe.
import sqlite3
con = sqlite3.connect(":memory:")
con.execute("CREATE TABLE t (city TEXT)")
con.execute("INSERT INTO t VALUES (?)", ("Nairobi",))
city = "Nairobi"
print(con.execute("SELECT * FROM t WHERE city = ?", (city,)).fetchall())
con.close()import sqlite3
con = sqlite3.connect(":memory:")
con.execute("CREATE TABLE t (city TEXT)")
con.executemany("INSERT INTO t VALUES (?)", [("Nairobi",), ("Mombasa",)])
print(con.execute("SELECT * FROM t WHERE city IN (?, ?)", ("Nairobi", "Kisumu")).fetchall())
con.close()import sqlite3
con = sqlite3.connect(":memory:")
con.execute("CREATE TABLE t (n INTEGER)")
con.execute("INSERT INTO t VALUES (:n)", {"n": 12})
print(con.execute("SELECT * FROM t").fetchall())
con.close()city = "Nairobi'; DROP TABLE t; --"
print("would become", f"SELECT * FROM t WHERE city = '{city}'")Pitfall
The last block only prints the dangerous string. It does not run it.