|
michahe
Anmeldungsdatum: 12. Dezember 2013
Beiträge: 874
|
Hallo,
für eine BASH-Anwendung wurde mir hier geholfen, eine SQL-Query richtig zu übergeben; noch einmal Danke an rklm! Zwei funktionierende Lösungen waren beschrieben: 1 | psql -U "user" -d "DBname" -c 'SELECT "ID-Name" FROM "SchemaName"."T Namen" where "Name" = '\''Petra Maier'\'';'
2 | psql -U "user" -d "DBname" -c "SELECT \"ID-Name\" FROM \"SchemaName\".\"T Namen\" where \"Name\"= 'Petra Maier'; "
Nun habe ich eine ähnliche Aufgabe mit PYTHON; die Verbindung mit dem Paket psycopg2 funktioniert bereits und ich versuche die SELECT-Befehle: | #!/usr/bin/env python3
# ...
curr = pg_connection.cursor() # Cursor erstellen mit Verbindungsobjekt
sql= "SELECT \"ID-Name\" FROM \"SchemaName\".\"T Namen\" where \"Name\"= 'Petra Maier';"
curr.execute(sql) # SQL-Befehl ausführen
data = curr.fetchall() # fetchall(): Alle Datensätze anzeigen
for row in data:
print(row)
|
Die Schreibweise gemäß Zeile 2 mit den umschließenden doppelten Anführungszeichen funktioniert, die Schreibweise aus Zeile 1 nicht. Nachtrag: Die m.E. übersichtlichtse ist:
| sql = """SELECT "ID-Name" FROM "SchemaName"."T Namen" where "Name" = 'Petra Maier';"""
|
Welche Maskierungsregeln sollte ich mir für PYTHON angewöhnen?
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11278
|
Siehe https://www.psycopg.org/docs/sql.html - das ist am besten das über Templates mit Platzhaltern zu lösen, weil damit dafür gesorgt wird, dass es immer ein korrektes Escaping gibt: 1
2
3
4
5
6
7
8
9
10
11
12 | from psycopg2 import sql
# ...
curr = pg_connection.cursor()
query = sql.SQL("select {field} from {table} where {pkey} = %s").format(
field=sql.Identifier("ID-Name"),
table=sql.Identifier("SchemaName", "T Namen"),
pkey=sql.Identifier("Name"))
curr.execute(sql, ("Petra Maier",)) #
data = curr.fetchall() # fetchall():
for row in data:
print(row)
|
|
|
michahe
(Themenstarter)
Anmeldungsdatum: 12. Dezember 2013
Beiträge: 874
|
Danke seahawk1986, erzeugt aber hier einen Fehler:
query = sql.SQL("select {field} from {table} where {pkey} = %s").format(
AttributeError: 'str' object has no attribute 'SQL'
An den Unterschieden zwischen Deiner Schreibweise
field=sql.Identifier("ID-Name"),
curr.execute(sql
und der aus der Quelle
field=sql.Identifier('my_name'),
curr.execute(query
liegt es nicht. Ratlose Grüße, Michael
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11278
|
Vermutlich hast du das Modul sql mit dem Query-String sql überschrieben. Damit kann man sich in Python gut selber in den Fuß schießen, wenn man seine Variablen-Namen nicht so wählt, dass die keine Built-Ins und importierten Module überschreiben.
|
|
michahe
(Themenstarter)
Anmeldungsdatum: 12. Dezember 2013
Beiträge: 874
|
Danke seahawk1986, Vermutlich hast du das Modul sql mit dem Query-String sql überschrieben.
Ja, hatte ich. Habe es umbenannt und zusätzlich allen altem Code auskommentiert. Fehler bleibt ...
Außerdem hatte ich Deine Zeile
curr = pg_connection.cursor() nicht übernommen. Diese liefert nun einen weiteren Fehler:
curr = pg_connection.cursor()
AttributeError: 'bool' object has no attribute 'cursor'
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11278
|
Ah, moment, da bin ich durcheinander gekommen, ich hatte sql nicht überall durch query ersetzt (Zeile 9):
1
2
3
4
5
6
7
8
9
10
11
12 | from psycopg2 import sql
# ...
curr = pg_connection.cursor()
query = sql.SQL("select {field} from {table} where {pkey} = %s").format(
field=sql.Identifier("ID-Name"),
table=sql.Identifier("SchemaName", "T Namen"),
pkey=sql.Identifier("Name"))
curr.execute(query, ("Petra Maier",))
data = curr.fetchall()
for row in data:
print(row)
|
|
|
michahe
(Themenstarter)
Anmeldungsdatum: 12. Dezember 2013
Beiträge: 874
|
Leider nicht:
query = sql.SQL("select {field} from {table} where {pkey} = %s").format(
NameError: name 'sql' is not defined
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11278
|
Dann hast du vermutlich diesen Import nicht in dein Skript übernommen:
|
|
michahe
(Themenstarter)
Anmeldungsdatum: 12. Dezember 2013
Beiträge: 874
|
Stimmt!
seahawk1986 Dann hast du vermutlich diesen Import nicht in dein Skript übernommen:
Ich hatte schon
Da fehlt mir noch das Verständnis. Mit beiden Zeilen funktioniert es, ohne die ursprüngliche mein alter Code nicht ...
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11278
|
michahe schrieb: Stimmt!
seahawk1986 Dann hast du vermutlich diesen Import nicht in dein Skript übernommen:
Ich hatte schon
Da fehlt mir noch das Verständnis.
Importe unter Python sind ein etwas komplexeres Thema: https://docs.python.org/3/reference/import.html - aber für den speziellen Fall geht es einfach nur darum, wie man das sql-Modul aus psycopg2 ansprechen will - wenn man psycopg2 alleine importiert, muss man das Submodul als Attribut von psycopg nutzen:
1
2
3
4
5
6
7
8
9
10
11
12 | import psycopg2
# ...
curr = pg_connection.cursor()
query = psycopg2.sql.SQL("select {field} from {table} where {pkey} = %s").format(
field=psycopg2.sql.Identifier("ID-Name"),
table=psycopg2.sql.Identifier("SchemaName", "T Namen"),
pkey=psycopg2.sql.Identifier("Name"))
curr.execute(query, ("Petra Maier",))
data = curr.fetchall()
for row in data:
print(row)
|
Wie man sieht, hat man damit schnell lange Zeilen und die Lesbarkeit leidet, daher ist
in der Hinsicht einfacher - man kann dann sql statt psycopg2.sql schreiben. Und um noch flexibler zu sein, kann man den Namen beim Import ändern, unter dem ein importiertes Modul verfügbar gemacht wird:
| import psycopg2.sql as foo
# bzw.
from psycopg2 import sql as foo
|
Oder man weist das nachträglich einer Variablen zu:
| import psycopg2
foo = psycopg2.sql
|
|
|
michahe
(Themenstarter)
Anmeldungsdatum: 12. Dezember 2013
Beiträge: 874
|
Danke seahawk1986! Importe unter Python sind ein etwas komplexeres Thema: https://docs.python.org/3/reference/import.html ...
Du hast mir sehr geholfen und ich habe wieder einmal einiges gelernt.
|
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13242
|
Ich habe leider nicht alle Details hier gelesen, aber üblicherweise sind Prepared Statements auch eine mögliche Lösung. Das ist ähnlich zu dem, was seahawk1986 vorgeschlagen hat, aber da macht das die Datenbank. Ich nehme an, die Python-Module für PostgreSQL unterstützen das auch. Insbesondere, wenn man dieselbe Query mehrfach mit verschiedenen Werten ausführen will, kann das auch Effizienzvorteile haben.
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11278
|
Soweit ich das gelesen habe gibt es eine Unterstützung für automatisch genutzte prepared Statements ab psycopg3: https://www.psycopg.org/psycopg3/docs/advanced/prepare.html - die werden angelegt, wenn man eine Abfrage wiederholt (standardmäßig mehr als 5 mal) nutzt. Aber auch mit einem prepared Statements muss man die Werte, mit denen die Abfrage gemacht werden soll, richtig escapen (auch wenn es einen grundsätzlich vor SQL-Injection schützt).
|
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13242
|
seahawk1986 schrieb: Soweit ich das gelesen habe gibt es eine Unterstützung für automatisch genutzte prepared Statements ab psycopg3: https://www.psycopg.org/psycopg3/docs/advanced/prepare.html - die werden angelegt, wenn man eine Abfrage wiederholt (standardmäßig mehr als 5 mal) nutzt.
Das löst aber das hier diskutierte Problem nicht, denn das arbeitet ja mit normalen Abfragen. Außerdem ist von der verlinkten Doku nicht klar, ob Muster erkannt werden, d.h., Abfragen, die sich nur durch wechselnde Werte unterscheiden aber nicht in der Struktur als ein PS erkannt werden.
Aber auch mit einem prepared Statements muss man die Werte, mit denen die Abfrage gemacht werden soll, richtig escapen (auch wenn es einen grundsätzlich vor SQL-Injection schützt).
Das ist nicht das, was ich als Unterstützung Prepared Statements kenne. Da ist das so, dass man einen Marker (manchmal ein Fragezeichen) an den Stellen einbaut, die man aktualisieren will. Dann setzt man die Werte direkt und führt es am Ende aus (Beispiel). Da muss dann nix maskiert werden, weil einem das die Library schon abnimmt.
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11278
|
rklm schrieb: Da muss dann nix maskiert werden, weil einem das die Library schon abnimmt.
Auch da gibt es soweit ich weiß ein paar Fallstricke - effektiv darf man sich nur darauf verlassen, dass Werte für eine Abfrage sicher sind, aber keine dynamisch gesetzten Identifier für Spalten und beim Anlegen des prepared Statement muss man natürlich auch korrekt Quoten.
|