Všimněte si, že s psycopg2 pro pole nemusíte provádět žádné zpracování řetězců. To je považováno za špatný postup, protože je náchylný k chybám a může - v nejhorším případě - vést k otevření injekčních útoků! Vždy byste měli používat vázané parametry. V níže uvedeném kódu vytvořím novou tabulku pouze s jedním sloupcem typu TEXT[] (jako ve vaší původní otázce). Poté přidám nový řádek a aktualizuji všechny. Takže uvidíte jak INSERT a UPDATE operace (ačkoli obě jsou téměř totožné).
Existuje však jeden Python gotcha, pokud aktualizujete pouze jednu hodnotu:cur.execute očekává příkaz SQL jako první argument a iterovatelný obsahující parametry, které mají být svázány jako druhý argument. Následující nebude práce:
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()
Důvodem je, že (new_values) je pythonem viděn jako new_values (závorky jsou v tomto případě vynechány, nejsou vnímány jako n-tice). To bude mít za následek chybu, že zadáte 3 hodnoty ('a' , 'b' a 'c' ) jako hodnoty, které mají být svázány, ale existuje pouze jeden zástupný symbol (%s ) v dotazu. Místo toho jej musíte zadat následovně (všimněte si přidané čárky na konci):
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()
To způsobí, že Python uvidí (new_values,) jako n-tici (která je iterovatelná) s jedním prvkem, který odpovídá zástupným symbolům dotazu. Podrobnější vysvětlení koncové čárky naleznete v oficiálních dokumentech o n-ticích.
Případně můžete také napsat [new_values] místo (new_values,) , ale - podle mého názoru - (new_values,) je čistší, protože n-tice jsou neměnné, zatímco seznamy jsou proměnlivé.
Zde je tabulka, se kterou jsem testoval:
CREATE TABLE foo (
values TEXT[]
);
A zde je kód Pythonu pro vkládání a aktualizaci hodnot:
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()
Při každém spuštění kód vloží nový řádek se stejnými hodnotami pole a poté provede aktualizaci bez WHERE klauzule, takže všechny hodnoty jsou aktualizovány. Po několika provedeních to dává následující výstup:
>>> 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']")