Merk op dat met psycopg2
u hoeft geen stringverwerking uit te voeren voor arrays. Dit wordt als een slechte gewoonte beschouwd omdat het foutgevoelig is en - in het ergste geval - kan leiden tot het openen van injectieaanvallen! U moet altijd gebonden parameters gebruiken. In de onderstaande code zal ik een nieuwe tabel maken met slechts één kolom met het type TEXT[]
(zoals in je oorspronkelijke vraag). Dan zal ik een nieuwe rij toevoegen en ze allemaal bijwerken. U ziet dus zowel een INSERT
en UPDATE
bewerking (hoewel beide vrijwel identiek zijn).
Er is echter één Python-probleem als je bijwerkt met slechts één waarde:cur.execute
verwacht de SQL-instructie als eerste argument en een iterable met de parameters die moeten worden gebonden als tweede argument. Het volgende zal niet werk:
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()
De reden is dat (new_values)
wordt door python gezien als new_values
(de haakjes vallen in dit geval weg, ze worden niet als tuple gezien). Dit resulteert in de fout dat u 3 waarden opgeeft ('a'
, 'b'
en 'c'
) als te binden waarden, maar er is slechts één tijdelijke aanduiding (%s
) in de zoekopdracht. In plaats daarvan moet u het als volgt specificeren (let op de toegevoegde komma aan het einde):
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()
Hierdoor ziet Python (new_values,)
als een tuple (wat een iterabel is) met één element, dat overeenkomt met de tijdelijke aanduidingen voor de query. Zie de officiële documenten over tupels voor een meer gedetailleerde uitleg van de volgkomma.
Als alternatief kunt u ook [new_values]
. schrijven in plaats van (new_values,)
, maar - naar mijn mening - (new_values,)
is schoner omdat tuples onveranderlijk zijn, terwijl lijsten veranderlijk zijn.
Dit is de tabel waarmee ik heb getest:
CREATE TABLE foo (
values TEXT[]
);
En hier is Python-code die zowel waarden invoegt als bijwerkt:
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()
Bij elke uitvoering voegt de code een nieuwe rij in met dezelfde arraywaarden en voert vervolgens een update uit zonder WHERE
clausule, zodat alle waarden worden bijgewerkt. Na een aantal uitvoeringen geeft I dit de volgende 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']")