在 pyodbc 中一次插入多行比 executemany 更快的解决方案

Faster solution than executemany to insert multiple rows at once in pyodbc

我想用一个插入语句插入多行。

我试过

params = ((1, 2), (3,4), (5,6))
sql = 'insert into tablename (column_name1, column_name2) values (?, ?)'
cursor.fast_executemany = True
cursor.executemany(sql, params)

但它是在参数上使用 运行 执行方法的简单循环。


我还尝试创建更长的插入语句,使其类似于 INSERT INTO tablename (col1, col2) VALUES (?,?), (?,?)...(?,?).

def flat_map_list_of_tuples(list_of_tuples):
    return [element for tupl in list_of_tuples for element in tupl])

args_str = ', '.join('(?,?)' for x in params)
sql = 'insert into tablename (column_name1, column_name2) values'
db.cursor.execute(sql_template + args_str, flat_map_list_of_tuples(params))

有效并将插入时间从 10.9 秒减少到 6.1 秒。

这个解决方案是否正确?它有一些漏洞吗?

Is this solution correct?

您提出的解决方案,即构建一个table value constructor (TVC), is not incorrect but it is really not necessary. pyodbc with fast_executemany=True and Microsoft's ODBC Driver 17 for SQL Server is about as fast as you're going to get short of using BULK INSERT or bcp as described in

Does it have some vulnerabilities?

由于您正在为参数化查询构建 TVC,因此您可以避免 SQL 注入漏洞,但仍有一些实施注意事项:

  1. 一个TVC一次最多可以插入1000行

  2. pyodbc通过调用系统存储过程执行SQL语句,SQL服务器中的存储过程最多可以接受2100个参数,所以你的行数TVC 可以插入也限制为 (number_of_rows * number_of_columns < 2100).

换句话说,您的 TVC 方法将限于 "chunk size" 1000 行或更少。实际计算在.

中描述