psycopg2:使用元组元组中的值更新表中的多行

问题描述 投票:0回答:2

我正在尝试使用元组的元组一次更新几行。 我从这篇文章中弄清楚了如何构建sql语句,但事实证明在

psycopg2
中实现它更具挑战性。 这是我所拥有的:

c = db.cursor()

new_values = (("Richard",29),("Ronald",30))

sql = """UPDATE my_table AS t 
         SET name = e.name 
         FROM (VALUES %s) AS e(name, id) 
         WHERE e.id = t.id;"""

c.execute(sql, (new_values,))

结果报错:

ProgrammingError: table "e" has 1 columns available but 2 columns specified
这是因为
FROM
子句被解释为:

FROM (VALUES (("Richard",29),("Ronald",30)))

而不是:

FROM (VALUES ("Richard",29),("Ronald",30))

我可以通过执行以下操作来解决此问题,但这似乎不安全:

import re
c = db.cursor()

sql = """UPDATE my_table AS t 
         SET name = e.name 
         FROM (VALUES %s) AS e(name, id) 
         WHERE e.id = t.id;"""
sql = c.mogrify(sql, (new_values,))

# Replace the first occurance of '((' with '('.
sql = sql.replace('((', '(',1)

# Replace the last occurance of '))' with ')'.
sql = re.sub(r'(.*)\)\)', r'\1)', sql)

sql = c.execute(sql)

有更好的方法吗?

python postgresql psycopg2
2个回答
32
投票

这篇文章为我指明了正确的方向。 extras.execute_values

的文档
还包含一个使用
UPDATE
子句的很好的示例。

c = db.cursor()
update_query = """UPDATE my_table AS t 
                  SET name = e.name 
                  FROM (VALUES %s) AS e(name, id) 
                  WHERE e.id = t.id;"""

psycopg2.extras.execute_values (
    c, update_query, new_values, template=None, page_size=100
)

0
投票

另外对于@tdnelson2答案 - 如果您使用某种列表理解来生成SET参数,则可能会出现时间戳问题(当您使用psycopg2插入时不会出现此问题)。然后您需要另外添加 ::timestamp 来设置块。就我而言,它看起来像这样:

UPDATE ods.dict_adr_spb as t
SET adrspb_house_id=e.adrspb_house_id, adrspb_t_creation_date=e.adrspb_t_creation_date::timestamp
FROM (VALUES %s) as e(adrspb_house_id, adrspb_t_creation_date)
WHERE e.adrspb_house_id = t.adrspb_house_id;
© www.soinside.com 2019 - 2024. All rights reserved.