sql >> Databasteknik >  >> RDS >> PostgreSQL

Python List till PostgreSQL Array

Observera att med psycopg2 du behöver inte göra någon strängbearbetning för arrayer. Detta anses vara lika dålig praxis eftersom det är felbenäget och kan - i värsta fall - leda till att det öppnas upp för injektionsattacker! Du bör alltid använda bundna parametrar. I koden nedan kommer jag att skapa en ny tabell med endast en kolumn med typen TEXT[] (som i din ursprungliga fråga). Sedan lägger jag till en ny rad och uppdaterar alla. Så du kommer att se både en INSERT och UPDATE operation (även om båda är ganska identiska).

Det finns dock en Python gotcha om du uppdaterar med bara ett värde:cur.execute förväntar sig SQL-satsen som första argument och en iterbar som innehåller parametrarna som ska bindas som andra argument. Följande kommer inte arbete:

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()

Anledningen är att (new_values) ses av python som new_values (föräldrarna tappas i detta fall, de ses inte som tupel). Detta kommer att resultera i felet att du anger 3 värden ('a' , 'b' och 'c' ) som värden som ska bindas, men det finns bara en platshållare (%s ) i frågan. Istället måste du specificera det enligt följande (märk kommatecken i slutet):

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()

Detta kommer att få Python att se (new_values,) som en tupel (vilket är en iterabel) med ett element, som matchar sökfrågans platshållare. För en mer detaljerad förklaring av det avslutande kommatecken, se de officiella dokumenten om tupler.

Alternativt kan du också skriva [new_values] istället för (new_values,) , men - enligt min mening - (new_values,) är renare eftersom tuplar är oföränderliga, medan listor är föränderliga.

Här är tabellen som jag testade med:

CREATE TABLE foo (
    values TEXT[]
);

Och här är Python-kod som både infogar och uppdaterar värden:

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()

Vid varje körning kommer koden att infoga en ny rad med samma arrayvärden, och sedan köra en uppdatering utan WHERE klausul, så alla värden uppdateras. Efter ett par avrättningar ger I detta följande utdata:

>>> 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. Hur man krymper/rensar ibdata1-fil i MySQL

  2. När ska man använda ärvda tabeller i PostgreSQL?

  3. Hur SHOW COLLATION fungerar i MariaDB

  4. Hur genererar jag ett slumptal för varje rad i ett T-SQL-val?