I'm attempting to update several rows at once using a tuple of tuples.
I figured out how to construct the sql statement from this post, but implementing it in psycopg2
has proven to be more challenging.
Here's what I have:
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,))
The result is an error: ProgrammingError: table "e" has 1 columns available but 2 columns specified
This is because the FROM
clause is being interpreted as:
FROM (VALUES (("Richard",29),("Ronald",30)))
instead of:
FROM (VALUES ("Richard",29),("Ronald",30))
I can work around this by doing the following but it seems unsafe:
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)
Is there a better way to do this?
This post pointed me in the right direction. The documentation for extras.execute_values
also contains a great example using the UPDATE
clause.
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
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With