从 pandas 数据帧执行 SQL 更新语句

Executing an SQL update statement from a pandas dataframe

上下文:我正在使用 MSSQL、pandas 和 pyodbc。

步骤:

现在如何执行辅助列中的 sql 代码,而不循环遍历每一行?

示例数据

前两列是通过查询得到的dbo.table,第三列存在但在数据库中为空。第四列仅存在于数据框中,用于准备对应更新 dbo.table

的 SQL 语句
ID raw processed strSQL
1 lorum.ipsum@test.com lorum ipsum UPDATE t SET t.processed = 'lorum ipsum' FROM dbo.table t WHERE t.ID = 1
2 rumlo.sumip@test.com rumlo sumip UPDATE t SET t.processed = 'rumlo sumip' FROM dbo.table t WHERE t.ID = 2
3 ... ... ...

我想以高效的方式在每一行中执行 SQL 脚本。

在我在对该问题的评论中推荐 .executemany() 之后,@Charlieface 随后的评论建议 table 值参数 (TVP) 将提供更好的性能。我认为这不会有太大的不同,但我错了。

对于现有的 table 名为 MillionRows

ID  TextField
--  ---------
 1  foo
 2  bar
 3  baz
…

和表格的示例数据

num_rows = 1_000_000
rows = [(f"text{x:06}", x + 1) for x in range(num_rows)]
print(rows)
# [('text000000', 1), ('text000001', 2), ('text000002', 3), …]

我的测试使用标准 executemany() 调用 cnxn.autocommit = Falsecrsr.fast_executemany = True

crsr.executemany("UPDATE MillionRows SET TextField = ? WHERE ID = ?", rows)

用了大约 180 秒(3 分钟)。

但是,通过创建用户定义的table类型

CREATE TYPE dbo.TextField_ID AS TABLE 
(
    TextField nvarchar(255) NULL, 
    ID int NOT NULL, 
    PRIMARY KEY (ID)
)

和一个存储过程

CREATE PROCEDURE [dbo].[mr_update]
@tbl dbo.TextField_ID READONLY
AS
BEGIN
    SET NOCOUNT ON;
    UPDATE MillionRows SET TextField = t.TextField
    FROM MillionRows mr INNER JOIN @tbl t ON mr.ID = t.ID
END

我用的时候

crsr.execute("{CALL mr_update (?)}", (rows,))

它在大约 80 秒内完成了相同的更新(不到一半的时间)。