Seltsames SQL Problem. SQL geht, aber Python schreibt nicht

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Nonickatall
User
Beiträge: 19
Registriert: Dienstag 31. Januar 2017, 21:33

Hallo,

ich habe eine MySQL Datenbank auf einem Ubuntu Server mit mehreren Tabellen, in die ich schreibe und auch lese.
Klappt immer und zuverlässig.

Nun habe ich eine neue Tabelle angelegt und versuche mit einem Python 3.4 Script in die Datenbank zu schreiben.
Ich bekomme weder in Eclipse auf Windows, noch in Thonny auf einem Raspberry, eine Fehlermeldung, aber das Script schreibt nicht.

Ich habe das Script ganz abgespeckt, um den Fehler zu finden. Das Script läuft in Eclipse sowohl in Thonny durch und gibt mir das Ergebnis von Print (SQL) aus. Es gibt keine Fehlermeldung.

Wenn ich aber dieses generierte SQL Statement aus Eclipse in DBeaver direkt als SQL Script ausführe, entsteht der Datensatz wie er soll. Das SQL Statement ist also richtig. Sonst müsste ja auch eine Fehlermeldung kommen.

Ich arbeite im DBeaver wie auch in den zwei IDEs mit dem selben Server, Benutzer und Passwort.

Ich stehe voll auf dem Schlauch und habe so etwas noch nie gehabt. Ich arbeite recht viel mit SQL und alle anderen sehr viel komplexeren Statements auf dem selben Server, in der selben Datenbank funktionieren.

Die Tabelle habe ich schon gelöscht und neu angelegt.

Hat jemand irgendeine Idee wo der Fehler liegt?

Code: Alles auswählen

#!/usr/bin/env python

import mysql.connector

#Verbindung zur SQL Datenbank herstellen
connection = mysql.connector.connect(host = "192.168.0.2", user = "User", passwd = "password", db = "db")

cursor = connection.cursor()
     
def Log_schreiben(herkunft, berechtigter, nummer, anforderung, aktion, parameter):
   print ("bla")
   SQL = ("INSERT INTO myhome.logdaten (herkunft) VALUES('" + herkunft + "');")
   print (SQL) 
   cursor.execute(SQL)
   cursor.close()
   connection.close()
        
Log_schreiben("tormann", "system", "", "Systemstart", "Systemstart", "")
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dir fehlt das commit. Das wird der DBeaver implizit machen.
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Nonickatall: Da fehlt das `commit()`. Und man formatiert keine Werte in eine Zeichenkette. Das ist im besten Fall unperformant, im mittleren Fall kaputt, und im schlechtesten Fall eine Sicherheitslücke (SQL injection).

Verbindung und Cusor sollten nicht auf Modulebene existieren. Eine Funktion zum schreiben in die Datenbank die das dann auch noch beides schliesst ohne es selbst geöffnet zu haben ist extrem schräg und im Grunde unbrauchbar.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python
from contextlib import closing
import mysql.connector


def logeintrag_schreiben(
    connection, herkunft, berechtigter, nummer, anforderung, aktion, parameter
):
    with closing(connection.cursor()) as cursor:
        cursor.execute(
            "INSERT INTO myhome.logdaten (herkunft) VALUES (%s)", herkunft
        )
        connection.commit()


def main():
    with closing(
        mysql.connector.connect(
            host="192.168.0.2", user="User", passwd="password", db="db"
        )
    ) as connection:
        logeintrag_schreiben(
            connection,
            "tormann",
            "system",
            "",
            "Systemstart",
            "Systemstart",
            "",
        )


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Nonickatall
User
Beiträge: 19
Registriert: Dienstag 31. Januar 2017, 21:33

Wow...

Danke... Ich habe das mit dem immer so gemacht und hatte nie Probleme beim schreiben der Daten mit dem fehlenden connection.commit()... Sehr seltsam.

Ich habe den Code erst nicht verstanden und musste da erstmal dran kauen , aber jetzt habe ich erheblichen Erkenntnisgewinn.

Der Beispiel Code hatte einen kleinen Fehler (Es fehlten die () um Ereignis) also:

Code: Alles auswählen

        cursor.execute(
            "INSERT INTO myhome.logdaten (herkunft) VALUES (%s)", (herkunft)
        )
weswegen er zunächst nicht funktionierte und ich habe nicht wirklich gute Erklärungen gefunden, was dieses %s bedeutet.

Aber jetzt habe ich es (glaube ich) verstanden.

Das heißt man kann die SQL Syntax und die Werte trennen, indem man erst die SQL Syntax schreibt, bei mehreren Feldern dann also:

Code: Alles auswählen

 "INSERT INTO myhome.logdaten (herkunft, berechtigter, nummer) VALUES (%s, %s, %s)"
und nach einem Komma, in Klammern, dann die eigentlichen Werte.

das %s oder %d für nummerische Werte, sind dann Platzhalter für die Daten, die da kommen.

Vollständig lautet es dann also:

Code: Alles auswählen

 "INSERT INTO myhome.logdaten (herkunft, berechtigter, nummer) VALUES (%s, %s, %s),
 			(herkunft, berechtigter, nummer)
Und das mit closing kannte ich auch nicht.

Also top Antwort...

Vielen Dank
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Nee, das ist nur %s. Und ich glaube auch nur bei MySQL. Die anderen Darenbankadapter benutzen da SQL-Standard-Platzhalter. Einer der Gründe warum ich eigentlich für alles lieber SQLAlchemy verwende.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
schubidu
User
Beiträge: 1
Registriert: Mittwoch 29. November 2023, 10:33

@__blackjack__
Mein Code sah so ähnlich aus wie von @Nonickatall
Jetzt schreibe ich Dank Dir korrekten und besseren Code.
Danke für die richtig gute und ausführliche Antwort!!
Antworten