如何基于排除列表长度动态构建SQLAlchemy查询(含NOT LIKE条件)
动态构建SQLAlchemy排除条件的解决方案
你可以通过链式调用where()方法或者and_()组合条件,动态根据排除列表的长度添加NOT LIKE等价的过滤逻辑。下面是两种直接可用的实现方式:
方法一:用not_like对应SQL的NOT LIKE
遍历排除列表,对每个排除项添加not_like条件,SQLAlchemy会自动将多个where()条件组合为AND逻辑:
from sqlalchemy import select, func, literal # 示例排除列表,可空或最多4个元素 exclude_names = ["Amazonia", "AmazonPrime"] # 构建基础查询(建议用literal替代原text写法,避免SQL注入风险) select_stmt = select( literal(company).label("company"), func.upper(table.c.name_cia), table.c.date, table.c.value ).where(func.upper(table.c.name_cia).contains(str(cia_name).upper())) # 动态追加排除条件 for exclude_name in exclude_names: upper_exclude = exclude_name.upper() select_stmt = select_stmt.where( func.upper(table.c.name_cia).not_like(f"%{upper_exclude}%") )
方法二:用~contains实现反向匹配
如果你更习惯SQLAlchemy的ORM风格,可以用取反操作符~实现和NOT LIKE一致的效果:
for exclude_name in exclude_names: upper_exclude = exclude_name.upper() select_stmt = select_stmt.where( ~func.upper(table.c.name_cia).contains(upper_exclude) )
核心细节
- 若排除列表为空,循环不会执行,查询逻辑和原代码完全一致,无需额外判断列表长度
- 统一转大写是为了保持大小写不敏感的过滤逻辑,和你原查询的规则对齐
- 替换
text(f"'{company}' as company")为literal(company).label("company")是生产环境的安全做法,能避免SQL注入隐患
内容的提问来源于stack exchange,提问作者FábioRB
相关产品推荐
相关产品推荐

