cursor.execute variable

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
rehgum
User
Beiträge: 22
Registriert: Montag 28. Februar 2022, 16:45

Hallo zusammen,

irgendwie stehe ich mal wieder auf dem Schlauch.
Ich baue eine MySQL Verbindung auf mit

Code: Alles auswählen

try:
  #Aufbau einer Verbindung
  fachdb = mysql.connector.connect(
    host= FachDB_Server ,
    user= FachDB_Benutzer ,
    password= FachDB_Passwort ,
    database= FachDB_Datenbank ,
    port= FachDB_Port
  )
  # Ausgabe des Hashwertes des initialisierten Objektes
  print(fachdb)
  print("Connected to database")
# Wenn ein Fehler vom Typ "mysql.connector.errors.ProgrammingError" aufgetreten ist...
except mysql.connector.errors.ProgrammingError:
  # Ausgabe einer Fehlermeldung auf der Konsole
  print("Fehler beim Aufbau der DB Verbindung aufgetreten!")

cursor = fachdb.cursor()
cursor.execute("SHOW TABLES")
for tbl in cursor:
  print(tbl)
funktioniert. Natürlich sind weiter oben entsprechnd die Variable definiert

Code: Alles auswählen

FachDB_Server = 'db4free.net'
FachDB_Benutzer = 'benutzer'
FachDB_Passwort = 'passwort'
FachDB_Datenbank = 'datenbank'
FachDB_Port = '3306' #Standard ist 3306
FachDB_Tabelle = 'barcodes'
FachDB_Spalte_Regalfachname = 'barcode'
FachDB_Spalte_LEDnummer = 'fach'
Nun möchte ich im cursor.execute entsprechende Variable mit einfliesen lassen.

Code: Alles auswählen

sql ='SELECT %s FROM %s WHERE %s = %s'
cursor.execute(sql, (FachDB_Spalte_LEDnummer, FachDB_Tabelle, FachDB_Spalte_Regalfachname, regalfach,))
Will er aber nicht.
Antwort:
mysql.connector.errors.ProgrammingError: 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''barcodes' WHERE 'barcode' = '300300300'' at line 1
Wenn ich die direkt definiere geht es:

Code: Alles auswählen

sql = SELECT fach FROM barcodes WHERE barcode = %s
 cursor.execute(sql, (regalfach,))
so funktioniert es. Aber wie bekomme ich es als Variable rein?

Danke
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@rehgum: Die Ersetzung funktioniert nur für SQL-*Werte*, nicht für Namen/Bezeichner. Weil die fest sein sollten. Wenn die variabel sind, deutet das in der Regel auf ein Problem beim Datenbankentwurf hin. Das macht nur Sinn wenn man Werkzeuge für Datenbanken schreibt die man nicht kennt.

Spätestens in dem Fall würde ich auch SQLAlchemy empfehlen statt sich da selbst SQL als Zeichenketten zusammenzubasteln.

Anmerkungen zum Quelltext: Eingerückt wird mit vier Leerzeichen pro Ebene, nicht mit zwei.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase). Namen sollten keine kryptischen Abkürzungen enthalten, oder gar nur daraus bestehen. Wenn man `table` meint, sollte man nicht nur `tbl` schreiben.

Kommentare sollen dem Leser einen Mehrwert über den Code geben. Faustregel: Kommentare beschreiben nicht *was* der Code macht, denn das steht da bereits als Code, sondern warum er das macht. Sofern das nicht offensichtlich ist. Offensichtlich ist in aller Regel auch was in der Dokumentation von Python und den verwendeten Bibliotheken steht.

Bei ``print(fachdb)`` wird kein Hashwert ausgegeben oder zumindest ist das *sehr* unwahrscheinlich. Vermutlich ist in der `repr()`-Darstellung die Objekt-ID enthalten wenn die auf `object.__repr__()` basiert.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Nachtrag: Die Fehlerbehandlung ist falsch, denn wenn ein Fehler beim Verbindungsaufbau auftritt gibst Du einfach nur aus, *dass* ein Fehler aufgetreten ist. Zum einen weiss man dadurch nicht welcher Fehler das genau war, was an der Stelle aber sehr interessant wäre um ihn zu beheben. Und zum anderen macht der Code danach weiter als wäre nichts passiert, wobei aber an der Stelle ja schon klar ist, dass `fachdb` gar nicht definiert ist, und der Code unweigerlich deshalb in die nächste Ausnahme laufen wird. An der Stelle wäre es sinnvoller die ursprüngliche Ausnahme einfach gar nicht zu behandeln.

Weder die Verbindung noch der Cursor werden geschlossen.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
from contextlib import closing

import mysql.connector

FACH_DB_SERVER = "db4free.net"
FACH_DB_BENUTZER = "benutzer"
FACH_DB_PASSWORT = "passwort"
FACH_DB_DATENBANK = "datenbank"
FACH_DB_PORT = "3306"  # Standard ist 3306.


def main():
    with closing(
        mysql.connector.connect(
            host=FACH_DB_SERVER,
            user=FACH_DB_BENUTZER,
            password=FACH_DB_PASSWORT,
            database=FACH_DB_DATENBANK,
            port=FACH_DB_PORT,
        )
    ) as fach_db:
        print(fach_db)
        print("Connected to database")

        with closing(fach_db.cursor()) as cursor:
            for table in cursor.execute("SHOW TABLES"):
                print(table)


if __name__ == "__main__":
    main()
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
rehgum
User
Beiträge: 22
Registriert: Montag 28. Februar 2022, 16:45

Danke für die Info,

ich bin ein absoluter Anfänger und werde deine Tipps versuchen soweit umzusetzen. Das script ist ja viel viel länger als die gezeigten ausschnitte.
Ich tüfftel mal weiter und setze deine Tipps um. Wenn ich fertig bin poste ich es mal zur strengen untersuchung. Auch wenn es dann funktioniert nehme ich gerne die Tipps mit wie man es besser oder sauberer machen kann.
Antworten