sql >> Database >  >> RDS >> PostgreSQL

Python-lijst naar PostgreSQL-array

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


  1. Tips voor het leveren van MySQL-databaseprestaties - deel één

  2. GROUP BY vs ORDER BY

  3. Alleen-lezen- en lees-schrijftransacties splitsen met JPA en Hibernate

  4. Wat is de beste manier om de SQL Server-verbinding programmatisch te testen?