python - postgres - sqlalchemy tutorial




Durch das Ausführen mehrerer Anweisungen mit Postgresql über SQLAlchemy werden Änderungen nicht beibehalten (2)

Dies funktioniert nicht - das Update hat keine Auswirkung:

command = "select content from blog where slug = 'meow'; update account_balance set balance=200 where id=1; select 1 from blog;"
content = db.engine.scalar(command)

Durch Umschalten der Anweisungen wird die Aktualisierung durchgeführt und Folgendes erfolgreich ausgewählt:

command = "update account_balance set balance=200 where id=1; select content from blog where slug = 'meow';"
content = db.engine.scalar(command)

Warum funktioniert das erste nicht? Es funktioniert in Pgadmin. Ich habe Autocommit mit Flask-Sqlalchemy aktiviert.

Ich mache gerade einen Workshop zum Thema SQL-Injection, bitte schreibe die Lösung nicht um!


Die automatische Festschreibung von SQLAlchemy prüft anhand der ausgegebenen Anweisungen, ob Daten geändert wurden oder nicht :

... implementiert SQLAlchemy eine eigene "Autocommit" -Funktion, die über alle Backends hinweg vollständig konsistent funktioniert. Dies wird erreicht, indem Anweisungen erkannt werden, die Datenänderungsoperationen darstellen, z. B. INSERT, UPDATE, DELETE sowie DDL-Anweisungen (Data Definition Language) wie CREATE TABLE, ALTER TABLE, und anschließend automatisch ein COMMIT ausgegeben wird, wenn keine Transaktion ausgeführt wird . Die Erkennung basiert auf dem Vorhandensein der Ausführungsoption autocommit=True in der Anweisung. Wenn es sich bei der Anweisung um eine reine Textanweisung handelt und das Flag nicht gesetzt ist, wird ein regulärer Ausdruck verwendet, um INSERT, UPDATE, DELETE sowie eine Reihe anderer Befehle für ein bestimmtes Backend zu ermitteln

Da mehrere Ergebnismengen auf SQLAlchemy-Ebene nicht unterstützt werden, wird bei der Erkennung in Ihrem ersten Beispiel einfach kein COMMIT ausgegeben, da die erste Anweisung ein SELECT ist, während es sich in Ihrem zweiten Beispiel um ein UPDATE handelt. Es wird nicht versucht, datenmodifizierende Anweisungen aus mehreren Anweisungen zu ermitteln.

Wenn Sie sich PGExecutionContext.should_autocommit_text() , werden Sie PGExecutionContext.should_autocommit_text() , dass es eine Regex-Übereinstimmung mit AUTOCOMMIT_REGEXP . Mit anderen Worten, es stimmt nur am Anfang des Textes überein.


Sie sollten db.engine.execute(...).first() wenn Sie alles ausführen und nur die erste Zeile erhalten möchten.





sqlalchemy