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