Nota che con psycopg2 non è necessario eseguire alcuna elaborazione di stringhe per gli array. Questa è considerata una cattiva pratica in quanto è soggetta a errori e può, nel peggiore dei casi, portare ad aprire attacchi di iniezione! Dovresti sempre usare parametri vincolati. Nel codice seguente creerò una nuova tabella con una sola colonna con il tipo TEXT[] (come nella tua domanda originale). Quindi aggiungerò una nuova riga e le aggiornerò tutte. Quindi vedrai entrambi un INSERT e UPDATE operazione (sebbene entrambi siano praticamente identici).
C'è un problema in Python se aggiorni con un solo valore:cur.execute si aspetta l'istruzione SQL come primo argomento e un iterabile contenente i parametri da associare come secondo argomento. Quanto segue non lavoro:
from psycopg2 import connect
conn = connect('dbname=exhuma')
cur = conn.cursor()
stmt = 'UPDATE foo SET example_value=%s'
new_values = ['a', 'b', 'c']
cur.execute(stmt, (new_values))
conn.commit()
Il motivo è che (new_values) è visto da Python come new_values (le parentesi vengono eliminate in questo caso, non sono viste come tuple). Ciò comporterà l'errore di fornire 3 valori ('a' , 'b' e 'c' ) come valori da associare, ma è presente un solo segnaposto (%s ) nella query. Devi invece specificarlo come segue (notare la virgola aggiunta alla fine):
from psycopg2 import connect
conn = connect('dbname=exhuma')
cur = conn.cursor()
stmt = 'UPDATE foo SET example_value=%s'
new_values = ['a', 'b', 'c']
cur.execute(stmt, (new_values,))
conn.commit()
Questo farà vedere a Python (new_values,) come una tupla (che è un iterabile) con un elemento, che corrisponde ai segnaposto della query. Per una spiegazione più dettagliata della virgola finale, vedere i documenti ufficiali sulle tuple.
In alternativa, puoi anche scrivere [new_values] invece di (new_values,) , ma - secondo me - (new_values,) è più pulito poiché le tuple sono immutabili, mentre le liste sono mutabili.
Ecco la tabella con cui ho provato:
CREATE TABLE foo (
values TEXT[]
);
Ed ecco il codice Python che inserisce e aggiorna i valori:
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()
Ad ogni esecuzione, il codice inserirà una nuova riga con gli stessi valori dell'array, quindi eseguirà un aggiornamento senza WHERE clausola, quindi tutti i valori vengono aggiornati. Dopo un paio di esecuzioni, questo fornisce il seguente output:
>>> 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']")