使用executemany执行查询报错:仅支持DML语句,execute却正常?
解决executemany()执行SELECT语句报错的问题
嘿,这个问题我之前也踩过坑,咱们来一步步理清楚:
为什么会报错?
你看到的ProgrammingError: executemany() can only execute DML statements其实已经说得很明确了:
executemany()这个方法从设计上就是用来执行DML语句的——也就是INSERT、UPDATE、DELETE这类修改数据库数据的操作。- 而
SELECT属于查询语句(DQL),不在它的支持范围内,所以直接用它来批量执行查询肯定会触发这个错误。
两种可行的解决方案
方案一:循环调用execute()(简单直接)
既然executemany()不能用来查数据,那咱们就回到最基础的方式:遍历你的参数列表,逐个调用execute()获取结果,最后把所有结果合并起来。示例代码如下:
# 初始化一个空列表用来存所有查询结果 all_results = [] # 遍历需要查询的donor参数 for donor_info in [ds[1].donor, ds[2].donor]: # 逐个执行查询 single_result = c.execute( "SELECT * FROM Donors WHERE firstname=:First AND lastname=:Last", donor_info ).fetchall() # 将单次查询结果加入总列表 all_results.extend(single_result)
这种方法逻辑简单,容易理解,适合数据量不大的场景。
方案二:构造批量查询SQL(更高效)
如果需要查询的批量数据比较多,循环调用的效率会偏低,这时候可以构造一条包含多个条件的SQL语句,一次性完成查询。核心思路是用IN子句来匹配多组(firstname, lastname)组合:
# 先把参数整理成(First, Last)的元组列表 donor_pairs = [(d['First'], d['Last']) for d in [ds[1].donor, ds[2].donor]] # 为每组参数生成对应的占位符,比如(:First0, :Last0), (:First1, :Last1) placeholder_str = ", ".join([f"(:First{i}, :Last{i})" for i in range(len(donor_pairs))]) # 拼接完整的SQL语句 sql_query = f"SELECT * FROM Donors WHERE (firstname, lastname) IN ({placeholder_str})" # 把参数整理成驱动能识别的字典格式 query_params = {} for idx, (first_name, last_name) in enumerate(donor_pairs): query_params[f"First{idx}"] = first_name query_params[f"Last{idx}"] = last_name # 执行批量查询 all_results = c.execute(sql_query, query_params).fetchall()
这种方法只需要和数据库建立一次查询交互,效率会比循环高很多,适合批量数据量大的场景。
内容的提问来源于stack exchange,提问作者user26472
相关产品推荐
相关产品推荐

