PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Elenco Python all'array PostgreSQL

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']")