Pyodbc executemany仅返回最后插入元素问题求助
问题原因
这是因为pyodbc的executemany方法在处理带有OUTPUT子句的INSERT语句时,行为有点特殊:SQL Server会为每一组插入的参数返回一个独立的结果集,但pyodbc的游标默认只会保留最后一个结果集。你调用cursor.fetchall()的时候,只能拿到最后一次插入操作产生的输出,前面的结果集都被跳过了——虽然所有数据都已经成功插入到数据库中。
解决方案
有两种可行的办法来获取所有插入行的OUTPUT结果:
方法1:改用单行多值INSERT语句(推荐)
把多个插入合并成一条SQL语句,这样SQL Server只会返回一个包含所有插入行的结果集,pyodbc就能一次性获取所有数据,而且数据库交互次数更少,效率更高。
修改后的代码示例:
import pyodbc def execute_side_effect_stmt(sql_stmt: str, params: tuple): with get_connection() as conn: cursor = conn.cursor() cursor.execute(sql_stmt, params) columns = [column[0] for column in cursor.description] results = cursor.fetchall() response = [dict(zip(columns, row)) for row in results] conn.commit() return response if response else '' # 构造支持多行插入的SQL语句 sql = """INSERT INTO dbo.events (sha, duration) OUTPUT Inserted.id, Inserted.sha VALUES (?, ?), (?, ?), (?, ?)""" # 将参数列表扁平化处理 params = ('123',1,'456', 2, '789', 3) result = execute_side_effect_stmt(sql, params)
方法2:循环执行单个INSERT语句
放弃使用executemany,改为遍历参数列表,逐个执行execute,每次执行后立即获取结果并收集起来。这种方式逻辑更直观,但多次执行会增加数据库交互次数,数据量较大时效率不如方法1。
修改后的代码示例:
import pyodbc def execute_side_effect_stmt(sql_stmt: str, params: list): with get_connection() as conn: cursor = conn.cursor() response = [] for param in params: cursor.execute(sql_stmt, param) columns = [column[0] for column in cursor.description] row = cursor.fetchone() if row: response.append(dict(zip(columns, row))) conn.commit() return response if response else '' sql = """INSERT INTO dbo.events (sha, duration) OUTPUT Inserted.id, Inserted.sha VALUES (?, ?)""" params = [('123',1),('456', 2), ('789', 3)] result = execute_side_effect_stmt(sql, params)
内容的提问来源于stack exchange,提问作者NicolaiF
相关产品推荐
相关产品推荐

