Обратите внимание, что с psycopg2
вам не нужно делать какие-либо обработки строк для массивов. Это считается плохой практикой, поскольку она подвержена ошибкам и может - в худшем случае - привести к открытию инъекционных атак! Вы всегда должны использовать связанные параметры. В приведенном ниже коде я создам новую таблицу с одним столбцом с типом TEXT[]
(как в вашем исходном вопросе). Затем я добавлю новую строку и обновлю все. Таким образом, вы увидите как операции INSERT
, так и UPDATE
(хотя оба они в значительной степени идентичны).
Существует один Python Гоча, хотя, если вы обновляете только одно значение: cur.execute
ожидает оператор SQL в качестве первого аргумента и Iterable, содержащий параметры, которые будут связаны в качестве второго аргумента. Ниже будет не работы:
stmt = 'UPDATE foo SET example_value=%s'
new_values = ['a', 'b', 'c']
cur.execute(stmt, (new_values))
Причина заключается в том, что (new_values)
рассматривается питоном, как new_values
(в круглых скобках опущены в этом случае, они не рассматриваются в качестве кортежа). Это приведет к ошибке в том, что вы задаете 3 значения ('a'
, 'b'
и 'c'
) в качестве значений, подлежащих привязке, но в запросе есть только один заполнитель (%s
). Вместо этого вы должны указать его следующим образом (обратите внимание на дополнительную запятую в конце):
stmt = 'UPDATE foo SET example_value=%s'
new_values = ['a', 'b', 'c']
cur.execute(stmt, (new_values,))
Это заставит Python видеть (new_values,)
как кортеж (который является итерацией) с одним элементом, который соответствует запросу местоблюститель , Более подробное объяснение конечной запятой см. В разделе the official docs on tuples.
В качестве альтернативы можно было бы написать [new_values]
вместо (new_values,)
, но - на мой взгляд - (new_values,)
чище, как кортежи неизменны, тогда как списки изменяемые.
Вот таблица, с которой я тестировал:
CREATE TABLE foo (
values TEXT[]
);
И вот Python код и вставки и обновления значений:
from psycopg2 import connect
conn = connect('dbname=exhuma')
cur = conn.cursor()
cur.execute('INSERT INTO foo VALUES (%s)', (['a', 'b'],))
print('>>> Before update')
cur.execute('SELECT * FROM foo')
for row in cur:
print(type(row[0]), repr(row[0]))
print('>>> After update')
cur.execute('UPDATE foo SET example_values = %s',
(['new', 'updated', 'values'],))
cur.execute('SELECT * FROM foo')
for row in cur:
print(type(row[0]), repr(row[0]))
cur.close()
conn.commit()
conn.close()
На каждом исполнении, код будет вставить новую строку с теми же значениями массива, а затем выполнить обновление без предложения WHERE
, поэтому все значения обновляются. После нескольких исполнений I это дает следующий результат:
>>> Before update
(<type 'list'>, "['new', 'updated', 'values']")
(<type 'list'>, "['new', 'updated', 'values']")
(<type 'list'>, "['new', 'updated', 'values']")
(<type 'list'>, "['new', 'updated', 'values']")
(<type 'list'>, "['new', 'updated', 'values']")
(<type 'list'>, "['a', 'b']")
>>> After update
(<type 'list'>, "['new', 'updated', 'values']")
(<type 'list'>, "['new', 'updated', 'values']")
(<type 'list'>, "['new', 'updated', 'values']")
(<type 'list'>, "['new', 'updated', 'values']")
(<type 'list'>, "['new', 'updated', 'values']")
(<type 'list'>, "['new', 'updated', 'values']")
Это довольно простая задача, что вы пробовали до сих пор? – alko