【问题标题】:Faster solution than executemany to insert multiple rows at once in pyodbc在 pyodbc 中一次插入多行比 executemany 更快的解决方案
【发布时间】:2019-07-25 03:18:55
【问题描述】:

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

我试过了

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 秒。

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

【问题讨论】:

  • "但是 [executemany 是一个] 参数上的简单循环,在后台运行执行方法" - 使用 pyodbc 和 fast_executemany = True 不一定是这种情况;它取决于 ODBC 驱动程序。您使用的是哪个 ODBC 驱动程序?
  • 适用于 SQL Server 的 ODBC 驱动程序 17

标签: python sql-server pyodbc


【解决方案1】:

这个解决方案正确吗?

您提出的解决方案,即构建一个table value constructor (TVC),并没有不正确,但实际上没有必要。 pyodbc 与 fast_executemany=True 和 Microsoft 的 SQL Server ODBC 驱动程序 17 的速度与使用 BULK INSERTbcp 中描述的 this answer 一样快。

它有一些漏洞吗?

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

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

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

换句话说,您的 TVC 方法将被限制为 1000 行或更少的“块大小”。实际计算见this answer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-13
    • 2018-06-21
    • 1970-01-01
    相关资源
    最近更新 更多