Python SQLite可选多WHERE条件查询的动态参数拼接问题求解
SQLite动态多条件零件检索的实现方案
核心思路是同步维护条件片段列表、参数值列表,每追加一个筛选条件,就同步往参数列表加对应的值,最终根据两个列表动态拼接SQL、生成参数元组,从根源解决占位符不匹配、SQL注入问题,同时天然兼容无筛选条件查全表的场景。
具体实现步骤
- 初始化两个空列表:
where_clauses存储合法的WHERE条件片段,params存储与占位符一一对应的参数值 - 逐个校验文本类输入项:过滤前后空格后非空的,才把对应条件片段加入
where_clauses,处理后的参数值加入params - 安全处理作业类型筛选:所有可选作业类型为代码硬编码的固定枚举值,仅根据复选框勾选状态,把固定合法值加入参数列表,禁止把用户可控的任意字符串直接拼接进SQL
- 拼接最终SQL:如果
where_clauses为空,直接执行全表查询;非空则用AND连接所有条件片段,拼接WHERE子句,把params转为元组传入execute方法即可
可直接复用的代码示例
假设你的PySimpleGUI控件key与表结构如下:
- 文本输入key:
-PART_NAME-(零件名称)、-PART_SERIES-(零件系列)、-PART_NUM-(零件编号)、-PART_SIZE-(零件尺寸) - 复选框key:
-FIT_CHECK-(Fit作业)、-WELD_CHECK-(Weld作业)、-ASSEMBLE_CHECK-(Assemble作业) - 数据表名为
parts,作业类型存储在job_type字段中
import sqlite3 def part_search(gui_values): where_clauses = [] params = [] # 处理文本类筛选条件 # 零件名称:模糊匹配 part_name = gui_values.get('-PART_NAME-', '').strip() if part_name: where_clauses.append("part_name LIKE ?") params.append(f"%{part_name}%") # 零件系列:模糊匹配 part_series = gui_values.get('-PART_SERIES-', '').strip() if part_series: where_clauses.append("part_series LIKE ?") params.append(f"%{part_series}%") # 零件编号:精确匹配,需要模糊可自行改为LIKE part_number = gui_values.get('-PART_NUM-', '').strip() if part_number: where_clauses.append("part_number = ?") params.append(part_number) # 零件尺寸:模糊匹配 part_size = gui_values.get('-PART_SIZE-', '').strip() if part_size: where_clauses.append("part_size LIKE ?") params.append(f"%{part_size}%") # 处理作业类型复选框:完全规避SQL注入 # 硬编码所有合法作业类型映射,不直接使用用户传入的字符串拼接SQL job_type_config = [ ('-FIT_CHECK-', 'Fit'), ('-WELD_CHECK-', 'Weld'), ('-ASSEMBLE_CHECK-', 'Assemble') ] selected_jobs = [type_val for widget_key, type_val in job_type_config if gui_values.get(widget_key, False)] if selected_jobs: # 生成与选中数量匹配的占位符 placeholder_str = ', '.join(['?'] * len(selected_jobs)) where_clauses.append(f"job_type IN ({placeholder_str})") params.extend(selected_jobs) # 拼接最终SQL base_query = "SELECT * FROM parts" if where_clauses: final_query = f"{base_query} WHERE {' AND '.join(where_clauses)}" else: final_query = base_query # 执行查询,参数顺序、数量与占位符完全匹配 conn = sqlite3.connect('parts.db') cursor = conn.cursor() cursor.execute(final_query, tuple(params)) search_result = cursor.fetchall() conn.close() return search_result
适配说明
- 如果你的表结构是用三个独立布尔字段存储作业适配情况(比如
is_fit/is_weld/is_assemble三个值为0/1的字段),只需要把作业类型处理部分的逻辑改为:勾选对应复选框时,向where_clauses加入is_fit = ?这类固定片段,同时向params加入1即可,核心的双列表同步逻辑不变 - 所有用户可修改的输入值全部通过
?占位符传入,不会存在SQL注入风险 - 无任何有效筛选条件时,
where_clauses为空,直接返回全表数据,不需要额外写特殊分支处理
内容的提问来源于stack exchange,提问作者colk84
相关产品推荐
相关产品推荐

