如何在 psycopg2 中使用 UPDATE/DELETE WHERE CURRENT OF?
How to use UPDATE/DELETE WHERE CURRENT OF in psycopg2?
我在 PostgreSQL 中使用服务器端游标和 psycopg2,基于 。
with conn.cursor(name='name_of_cursor') as cursor:
query = "SELECT * FROM tbl FOR UPDATE"
cursor.execute(query)
for row in cursor:
# process row
在处理每一行时,我想使用 PostgreSQL 的 UPDATE tbl SET ... WHERE CURRENT OF name_of_cursor
(docs) 更新行中的几个字段,但似乎,当 for 循环进入并且 row
已设置,服务器端游标的位置在不同的记录中,因此虽然我可以 运行 命令,但更新了错误的记录。
如何确保结果迭代器与光标位于相同的位置? (也最好以一种不会使循环比使用 ID 更新更慢的方式)
更新不同记录的原因是因为 psycopg2 在内部执行 FETCH FORWARD 1000
(或任何默认块大小),将光标定位在块的末尾。您可以通过一次获取一条记录来覆盖它:
updcursor = conn.cursor()
with conn.cursor(name='name_of_cursor') as cursor:
cursor.itersize = 1 # to make server-side cursor be in the same position as the iterator
cursor.execute('SELECT * FROM tbl FOR UPDATE')
for row in cursor:
# process row...
updcursor.execute('UPDATE tbl SET fld1 = %s WHERE CURRENT OF name_of_cursor', [val])
上面的代码片段将更新正确的记录。请注意,您不能使用相同的光标进行选择和更新,它们必须是不同的光标。
性能
将 FETCH 大小减小到 1 会大大降低检索性能。如果您从与 PostgreSQL 服务器不同的主机迭代大型数据集(这可能是您正在搜索服务器端游标的情况),我绝对不建议使用此技术。
我最终使用了将记录导出到 CSV 的组合,然后稍后使用 COPY FROM
(使用函数 copy_expert)导入它们。
我在 PostgreSQL 中使用服务器端游标和 psycopg2,基于
with conn.cursor(name='name_of_cursor') as cursor:
query = "SELECT * FROM tbl FOR UPDATE"
cursor.execute(query)
for row in cursor:
# process row
在处理每一行时,我想使用 PostgreSQL 的 UPDATE tbl SET ... WHERE CURRENT OF name_of_cursor
(docs) 更新行中的几个字段,但似乎,当 for 循环进入并且 row
已设置,服务器端游标的位置在不同的记录中,因此虽然我可以 运行 命令,但更新了错误的记录。
如何确保结果迭代器与光标位于相同的位置? (也最好以一种不会使循环比使用 ID 更新更慢的方式)
更新不同记录的原因是因为 psycopg2 在内部执行 FETCH FORWARD 1000
(或任何默认块大小),将光标定位在块的末尾。您可以通过一次获取一条记录来覆盖它:
updcursor = conn.cursor()
with conn.cursor(name='name_of_cursor') as cursor:
cursor.itersize = 1 # to make server-side cursor be in the same position as the iterator
cursor.execute('SELECT * FROM tbl FOR UPDATE')
for row in cursor:
# process row...
updcursor.execute('UPDATE tbl SET fld1 = %s WHERE CURRENT OF name_of_cursor', [val])
上面的代码片段将更新正确的记录。请注意,您不能使用相同的光标进行选择和更新,它们必须是不同的光标。
性能
将 FETCH 大小减小到 1 会大大降低检索性能。如果您从与 PostgreSQL 服务器不同的主机迭代大型数据集(这可能是您正在搜索服务器端游标的情况),我绝对不建议使用此技术。
我最终使用了将记录导出到 CSV 的组合,然后稍后使用 COPY FROM
(使用函数 copy_expert)导入它们。