Benutzer-Werkzeuge

Webseiten-Werkzeuge


python:psycopg

Dies ist eine alte Version des Dokuments!


  • Postgres-Datenbank-Treiber für Python

Transaction-Handling

  • jede Aktion in der Datenbank (jedes aufrufen von cursor.execute()) erzeugt eine Transaktion (wenn nicht eine offene besteht)
  • per Default ist autocommit=False für Datenbankverbindungen
    • nach dem Absetzen von cursor.execute wird die Transaktion also nicht committed
  • es muss also explizit committed werden

Es gibt mehrere Möglichkeiten das commit oder rollback über Context-Blöcke zu steuern

with psycopg.connect(someconnectionninformation) as connection:
    cursor = connection.cursor()
    cursor.execute(somestatement)
    cursor.execute(someotherstatement)

Außerdem wird die Verbindung zur Datenbank danach geschlossen

with psycopg.connect(someconnectionninformation) as connection:
    cursor = connection.cursor()
    with connection.transaction():
        cursor.execute(somestament)
        cursor.execute(somestament)
    with connection.transaction():
        cursor.execute(somestament)
        cursor.execute(somestament)

Man muss allerdings aufpassen, wenn außerhalb der transaction-Blöcke Statements ausgeführt werden, dann starten diese implizit Transaktionen und die transaction-Blöcke erstellen dann nur savepoint sub-transactions.
Ggf. sollte man beim connect dann autocommit=True setzen, dann werden alle Statements außerhalb der transaction-Blöcke als eigene Transaktionen gehandhabt, die sofort commited sind.

Server-side binding

  • Technik bei der das SQL-Statement und die Werte getrennt an die Datenbank gesendet werden
  • Ziel ist u.a. die Vermeidung von sql-Injection durch Trennung von Statement und Werten
    • die Datenbank wertet Werte nicht aus → dadurch können sie keine Statements enthalten
  • ist auf Statement limitiert
    • ein execute()-Call kann nur ein Statement enthalten das Server-side-binding macht

conn.execute(insert into whatever values(%s); select * from somethingelse where id = %s, ("firstvalue", "secondvalue"))

  • obiges funktioniert nicht
  • wenn mehrere Statements vorhanden sind, aber nur eins Server-side-binding nutzt funktioniert das

Mischen von Transaktions- und Nicht-Transaktionsstatements in einem execute

  • die meisten Kommandos (auch DDL-Kommandos) können in einer Transaktion ausgeführt werden
    • es gibt aber Ausnahmen wie „create database“
  • Postgres fasst intern alle Statements eines cursor()-Aufrufs zu einer Transaktion zusammen
    • oder auch
  • ^ deswegen kann man im gleichen execute()-Aufruf keine Kommandos mischen die Transaktionen unterstützen und solche die es nicht tun

Temporary tables

  • Existieren nur in der Session in der sie erstellt wurden
    • verschiedene Verbindungen zur Datenbank können also die gleiche Tabelle ggf. mit unterschiedlichem Inhalt haben

create temp table somename (somerow varchar) on commit delete rows;

  • „on commit“ definiert was bei einem Commit mit der Tabelle passieren soll
    • preserve_rows (Default in postgres, aber nicht im Standard) → erhalte die Tabelle wie sie ist, inkl. Inhalt
    • delete rows → truncate aka. lösche alle Einträge, aber erhalte die leere Tabelle
    • drop → lösche die Tabelle

Copy

  • Eigentlich eine Möglichkeit eine größere Menge Einträge aus Dateien (oder stdin) einzulesen oder nach stout/Datei auszugeben
  • ist meist effizienter als insert into

Daten in eine Tabelle einfügen:

    with cursor.copy("copy table_name (column1, column2) from stdin") as copy:
        for record in records:
            copy.write_row(record)

Daten aus einer Tabelle auslesen:

    with cursor.copy("copy table_name (column1, column2) to stdout") as copy:
        for record in copy.rows():
            Some action

python/psycopg.1688156914.txt.gz · Zuletzt geändert: 2023/06/30 22:28 von root