python中用sqlite3执行参数化查询的正确写法是使用?或:name占位符,参数必须为tuple(单值加逗号)或dict,严禁字符串拼接、f-string或%s;例如cursor.execute("select * from users where id = ?", (user_id,))。

Python中用sqlite3执行参数化查询的正确写法
直接拼接字符串构造SQL(比如 "SELECT * FROM users WHERE name = '" + name + "'" )是SQL注入的根源。Python的sqlite3模块原生支持参数化查询,但只认?占位符或命名占位符:name,不支持字符串格式化或f-string插值。
常见错误是把参数当字符串拼进SQL里,或者误用%s(这是MySQLdb/PyMySQL的风格,sqlite3不认)。
-
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))✅ 正确:单值元组末尾必须加逗号 -
cursor.execute("SELECT * FROM users WHERE name = :name", {"name": "Alice"})✅ 命名参数更易读,适合多参数 -
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")❌ 危险:f-string直接展开变量 -
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))❌ 报错:sqlite3不识别%s
PostgreSQL和MySQL驱动对参数占位符的要求不同
不同数据库驱动约定不同,不能混用。用错占位符不会报语法错误,而是把参数当字面量处理,导致查不到数据或逻辑异常。
- PostgreSQL(
psycopg2)只接受%s,哪怕值是字符串也要用%s:cursor.execute("SELECT * FROM logs WHERE level = %s", ("ERROR",)) - MySQL(
pymysql或mysql-connector-python)也用%s,但mysql-connector额外支持%(name)s命名方式 - SQLite(
sqlite3)只认?或:name,用%s会当作普通字符串字面量
一个典型坑是:本地用SQLite开发时写了?,上线换PostgreSQL后没改占位符,结果所有WHERE条件都失效——因为?被当成字符串字面量而非参数。
批量插入时别用循环+单条execute()
虽然单条execute()加参数能防注入,但循环插入1000条数据会触发1000次网络往返(MySQL/PG)或磁盘刷写(SQLite),性能极差,还可能撑爆连接池。
- 用
executemany()代替循环:cursor.executemany("INSERT INTO items VALUES (?, ?)", data_list) -
data_list必须是元组或列表的列表,每个子项长度要匹配SQL中占位符个数 - PostgreSQL的
psycopg2支持execute_batch()或execute_values()(需extras模块),比原生executemany快得多 - 切忌在循环里拼出一长串
VALUES (…), (…), …——这又回到字符串拼接,失去参数化意义
ORM如SQLAlchemy默认安全,但text()和execute()仍需手动参数化
SQLAlchemy的query.filter(User.name == name)这类表达式是安全的,它内部生成带参数的SQL。但一旦你用text()写原始SQL,就必须自己管参数。
-
session.execute(text("SELECT * FROM users WHERE role = :role"), {"role": "admin"})✅ 安全 -
session.execute(text(f"SELECT * FROM users WHERE role = '{role}'"))❌ 注入漏洞照旧 -
session.execute(text("SELECT * FROM users WHERE id IN :ids"), {"ids": tuple(id_list)})❌ 错误::ids不能展开为多个值,IN子句需动态生成占位符
IN子句是高频陷阱:没有通用占位符支持变长列表,必须根据id_list长度动态生成?, ?, ?再传参,或者改用tuple()配合数据库特定函数(如PostgreSQL的ANY(%s))。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











