
在 SQLAlchemy 中,使用 IN 子句时需注意:col1.in_(vals1) & col2.in_(vals2) 会进行笛卡尔组合匹配,而非按序配对;正确方式是用 or_ 拼接多个 (col1==v1) & (col2==v2) 条件,或在 PostgreSQL 中使用 tuple_ 实现原生元组匹配。
在 sqlalchemy 中,使用 `in` 子句时需注意:`col1.in_(vals1) & col2.in_(vals2)` 会进行笛卡尔组合匹配,而非按序配对;正确方式是用 `or_` 拼接多个 `(col1==v1) & (col2==v2)` 条件,或在 postgresql 中使用 `tuple_` 实现原生元组匹配。
当需要根据一组字段对(如 (name, surname))精确查找记录时,常见误区是分别对各字段使用 .in_(),例如:
names = ["Mario", "Giovanni"] surnames = ["Rossi", "Bianchi"] stmt = select(User).where(User.name.in_(names)).where(User.surname.in_(surnames))
这等价于 WHERE name IN ('Mario', 'Giovanni') AND surname IN ('Rossi', 'Bianchi'),将匹配所有组合:('Mario','Rossi')、('Mario','Bianchi')、('Giovanni','Rossi')、('Giovanni','Bianchi') —— 显然超出了预期(仅想查 ('Mario','Rossi') 和 ('Giovanni','Bianchi'))。
✅ 正确解法一:通用跨数据库方案(推荐)
使用 sqlalchemy.or_() 动态构建“或”条件链,每个子条件为完整字段对的等值匹配:
from sqlalchemy import or_
users = [("Mario", "Rossi"), ("Giovanni", "Bianchi")]
with Session(engine) as session:
stmt = select(User).where(
or_(
*( (User.name == name) & (User.surname == surname)
for name, surname in users )
)
)
results = session.execute(stmt).scalars().all()
print(results)
# 输出: [User(name='Mario', surname='Rossi'), User(name='Giovanni', surname='Bianchi')]
该写法清晰、可读性强,且兼容所有主流数据库(SQLite、MySQL、PostgreSQL、Oracle 等),是生产环境首选。
✅ 正确解法二:PostgreSQL 专属优化方案
若确定使用 PostgreSQL,可借助 tuple_ 表达式实现语义更简洁、执行更高效的原生元组 IN 查询:
from sqlalchemy.sql.expression import tuple_
with Session(engine) as session:
stmt = select(User).where(
tuple_(User.name, User.surname).in_(users)
)
results = session.execute(stmt).scalars().all()
print(results)
生成的 SQL 类似:
SELECT * FROM user_account
WHERE (name, surname) IN (('Mario', 'Rossi'), ('Giovanni', 'Bianchi'));
此语法被 PostgreSQL 原生支持,查询计划更优,但不适用于 SQLite 或 MySQL(8.0.19 之前),使用前请确认数据库兼容性。
⚠️ 注意事项:
- 避免对空列表调用
or_(*[])(会报错),建议增加判空逻辑:if users: ... else: []; - 当
users列表极大(如数千对)时,or_方式可能导致 SQL 过长或参数过多,此时应考虑分批查询或改用临时表; -
tuple_.in_()在 SQLAlchemy 2.0+ 中稳定支持,旧版本需升级或使用tuple_(...).in_([...])的等效写法。
总结:字段对精确匹配的本质是「逻辑或」而非「多字段独立 in」。优先采用 or_ + and_ 组合保证兼容性与可维护性;仅在明确使用 PostgreSQL 且性能敏感场景下,选用 tuple_ 优化。










