【问题标题】:How to use UPDATE/DELETE WHERE CURRENT OF in psycopg2?如何在 psycopg2 中使用 UPDATE/DELETE WHERE CURRENT OF?
【发布时间】:2021-05-26 19:13:44
【问题描述】:

我在 PostgreSQL 中使用带有 psycopg2 的服务器端游标,基于 this well-explained answer

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 更新更慢的方式)

【问题讨论】:

    标签: python postgresql psycopg2


    【解决方案1】:

    更新不同记录的原因是因为 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])
    

    上面的sn-p会更新正确的记录。请注意,您不能使用相同的光标进行选择和更新,它们必须是不同的光标。

    性能

    将 FETCH 大小减小到 1 会大大降低检索性能。如果您从与 PostgreSQL 服务器不同的主机迭代大型数据集(这可能是您正在搜索服务器端游标的情况),我绝对不建议使用此技术。

    我最终使用了将记录导出到 CSV 的组合,然后使用 COPY FROM(使用函数 copy_expert)导入它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-23
      • 2020-10-30
      • 1970-01-01
      • 1970-01-01
      • 2022-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多