python
with psycopg.connect(conninfo) as conn:
cur = conn.cursor()
cur.execute('''
CREATE TABLE IF NOT EXISTS kunden (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
stadt TEXT,
umsatz NUMERIC(10, 2) DEFAULT 0
)
''')
cur.execute(
'INSERT INTO kunden (name, stadt, umsatz) VALUES (%s, %s, %s) RETURNING id',
('Anna', 'Wien', 120.50),
)
neue_id = cur.fetchone()[0]
cur.execute('SELECT id, name, umsatz FROM kunden WHERE stadt = %s', ('Wien',))
for zeile in cur.fetchall():
print(zeile)
Die wichtigste Regel: Werte immer als Parameter übergeben, niemals per f-String in das SQL einbauen.
python
# FALSCH: SQL-Injection möglich, wenn name aus einer Eingabe stammt
cur.execute(f"SELECT * FROM kunden WHERE name = '{name}'")
# RICHTIG: die Datenbank behandelt den Wert als Wert, nie als SQL-Befehl
cur.execute('SELECT * FROM kunden WHERE name = %s', (name,))
Das Platzhalterzeichen ist immer %s, unabhängig vom Datentyp. Die Werte stehen als Tupel (oder Liste) im zweiten Parameter. Bei einem einzelnen Wert braucht das Tupel das Komma: (name,). Alternativ mit Namen: '... WHERE name = %(name)s' und ein Dictionary {'name': name}. Platzhalter gelten nur für Werte, nicht für Tabellen- oder Spaltennamen.
| Cursor-Methode | Wirkung |
|---|---|
execute(query, params=None) |
Führt einen Befehl aus |
executemany(query, params_seq) |
Führt denselben Befehl für viele Parametersätze aus (Massen-Insert) |
fetchone() |
Nächste Zeile oder None |
fetchmany(size) |
Bis zu size Zeilen |
fetchall() |
Alle Zeilen als Liste (nicht bei riesigen Ergebnissen) |
rowcount |
Anzahl betroffener oder gelieferter Zeilen |
description |
Spaltennamen und Typen des Ergebnisses |
python
zeilen = [('Ben', 'Graz', 80), ('Cem', 'Wien', 210)]
cur.executemany('INSERT INTO kunden (name, stadt, umsatz) VALUES (%s, %s, %s)', zeilen)