Dateneinträge in Datenbank ändern SQLlite

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
pleasehelp!
User
Beiträge: 28
Registriert: Donnerstag 15. November 2018, 20:44

Hallo,
ich möchte eine Benutzerführung und einen Datenbankzugriff über python schreiben. Das Grundgerüst steht, nur wenn ich Einträge ändern möchte funktioniert etwas mit der Schleife nicht. Ich habe es erst mit einer while True versucht, aber dann kam ich nicht mehr aus der Schleife ohne das Programm abzubrechen. Jetzt leider etwas umständlich, aber immerhin funktioniert es, wenn die ANgaben stimmen, nur weiss ich nicht wie ich es schrieben kann, dass man als Benutzer erneut eine Schülernummer eingeben kann. Diesen Vorgang würde ich auch gerne für weitere Funktionen auslagern... Wenn jemand Ideen hat gerne. Im Anschluss ist die eine Funktion bei der die Rückfrage nicht funktioniert.

Code: Alles auswählen

def changeNN(conn):
    c = conn.cursor()
    s = input("Geben Sie die Schülernummer ein: ")
    showSchueler(conn, s)
    print("Sind das die richtigen Schülerangaben?")
    WahlR = input("Ja oder Nein: ")
    WahlR = WahlR.lower()
    fragebeantwortet = 0
    while fragebeantwortet == 0:
        if WahlR == "ja":
            NN = input("Geben Sie den neuen Nachnamen ein: ")
            c.execute('''UPDATE Schueler SET name = ? WHERE schuelernr = ?''', (NN, s))
            conn.commit()
            fragebeantwortet = 1
        elif WahlR == "nein":
            s = input("Bitte geben Sie eine neue Schülernummer ein: ")
            showSchueler(conn,s)
            #eigentlich zurück zur Frage
    return s
Vielen Dank schonmal!
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du solltest deinen Code in verschiedene Funktionen aufteilen - die eigentliche Arbeit mit der Datenbank, genauso wie das oeffnen derselben, gehoert nicht vermischt mit der Ein/Ausgabe. Fuer eine Flagge wie fragebeantwortet benutzte man in Python boolsche Werte, True oder False. Und dann schreibt man auch nicht

Code: Alles auswählen

while fragebeantwortet == False
(oder 0)

sonden einfach nur

Code: Alles auswählen

while not fragebeantwortet:
Und in deine while-Schleife liegt auch das Problem. Die musst du so umschreiben, dass du statt sie zu verlassen blos weil ein Benutzer veraendert wurde du ein Abbruchkriterium definierst, zB Schuelernummer -1. Dann fragst du so lange nach, bis jemand diese ungueltige Nummer eingibt.
pleasehelp!
User
Beiträge: 28
Registriert: Donnerstag 15. November 2018, 20:44

@__deets__ Danke, aber wie kann ich ein Abbruchkriterium definieren, soll man das dann schon beim CREATE von der Tabelle oder in dem elif irgendetwas schreiben.

Code: Alles auswählen

def changeNN(conn):
    c = conn.cursor()
    s = input("Geben Sie die Schülernummer ein: ")
    showSchueler(conn, s)
    print("Sind das die richtigen Schülerangaben?")
    WahlR = input("Ja oder Nein: ")
    WahlR = WahlR.lower()
    while not fragebeantwortet:
        if WahlR == "ja":
            NN = input("Geben Sie den neuen Nachnamen ein: ")
            c.execute('''UPDATE Schueler SET name = ? WHERE schuelernr = ?''', (NN, s))
            conn.commit()
        elif WahlR == "nein":
            #noch unklar
    return s
geht das dann so?
Benutzeravatar
__blackjack__
User
Beiträge: 13106
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@pleasehelp!: Nein das geht nicht weil `fragebeantwortet` offensichtlich nirgends definiert ist. In die ``while``-Schleife muss halt alles rein was sich wiederholen soll, sonst wird es nicht wiederholt.

Am besten eine ``while True:``-Schleife um das ganze und nach der Eingabe der Schülernummer prüfst Du zum Beispiel ob es eine -1 oder eine Leereingabe war, und falls ja, dann gehst Du mit ``break`` raus aus der Schleife.

Du musst Dich übrigens besser um Datentypen kümmern, es sei denn die Schülernummer ist tatsächlich eine Zeichenkette und keine Zahl.

Namen schreibt man in Python übrigens klein_mit_unterstrichen. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). Und die Abkürzungen solltest Du Dir abgewöhnen. Namen sollen dem Leser vermitteln wofür der Wert dahinter steht, und nicht zum rätseln zwingen. NN ist eine übliche Abkürzung für Normalnull, aber sicher nicht für „Nachname“. Und wofür steht das `R` in `WahlR`?

Man sollte auch deutsch und englisch nicht mischen.

Neben der Trennung von Datenhaltung und Benutzerinteraktion, die __deets__ schon angesprochen hat, macht es oft Sinn Code zum neu anlegen eines Datensatzen und verändern eines Datensatzes zusammenzufassen, so das neu anlegen das ”verändern” eines leeren Datensatzes ist. Ich hoffe an der Stelle auch, dass Du da nicht für jede Spalte von der `Schueler`-Tabelle eine eigene `change*()`-Funktion hast. Die sähen dann ja alle fast gleich aus, und man könnte eine Menge heraus ziehen. Am Ende wahrscheinlich sogar so weit, dass man *eine* Funktion hat, und der irgendwie per Daten/Argument die Beschaffenheit eines Datensatzes mitteilt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
pleasehelp!
User
Beiträge: 28
Registriert: Donnerstag 15. November 2018, 20:44

Vielen Dank und es funktioniert an sich jetzt, nur wie schon vermutet ist alles gedoppelt. Ich arbeite nur sehr wenig mit Python, wäre nett wenn ich zu der Auslagerung dieser Abfrage eine Lösung bekomme, damit ich diese wenigstens nich überall neu schreiben muss und ich wollte den Datentyp zu int ändern und habe eine Funktion dafür geschrieben, allerdings habe ich dann eine Fehlerausgabe bekommen, die meinte die Parameter könnten nicht verwendet werden.
Also einmal der Ausschnitt wobei ich Hilfe bräuchte die Abfrage nach den richtigen Schülerangaben auszulagern:

Code: Alles auswählen

def changeNN(conn):
    c = conn.cursor()
    while True:
        s = input("Geben Sie die Schülernummer ein: ")
        showSchueler(conn, s)
        print("Sind das die richtigen Schülerangaben?")
        WahlR = input("Ja oder Nein: ")
        WahlR = WahlR.lower()
        if WahlR == "ja":
            NN = input("Geben Sie den neuen Nachnamen ein: ")
            c.execute('''UPDATE Schueler SET name = ? WHERE schuelernr = ?''', (NN, s))
            conn.commit()
            break
        elif WahlR == "nein":
            pass
    return s
Das ist die Funktion damit ich einen input als int definiere, weil könnte ja sein, dass ich etwas falsch gemacht habe...

Code: Alles auswählen

def zahl(frage):
    Zahl = ""
    while Zahl == "" :
        text = input(frage)
        try:
            Zahl = int(text)
        except:
            pass
    return Zahl
Danke @__blackjack__
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn es einen Fehler gibt, solltest Du ihn exakt so hier posten, wie er erscheint, inklusive Traceback.

Nakte excepts sollte man nicht verwenden, hier willst Du einen ValueError abfangen.
Wenn man einen Dummy-Wert braucht, um eine while-Schleife zu starten, will man eigentlich eine while-True-Schleife:

Code: Alles auswählen

def ask_number(prompt):
    while True:
        try:
            return int(input(prompt))
        except ValueError:
            pass
Was hast Du von dem, was __blackjack__ geschrieben hat, umgesetzt??
pleasehelp!
User
Beiträge: 28
Registriert: Donnerstag 15. November 2018, 20:44

@Sirius3
Hallo, ich habe das mit der while True - Schleife umgesetzt allerdings kann ich nicht mehr alle Namen ändern und das mit dem Auslagern kann ich eben noch nicht.
Das ist meine Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "F:\Informatik\Programme\python\python\meineSkripte\Klasse 12\SQL_python_projekt.py", line 447, in <module>
    mainmenu(conn)
  File "F:\Informatik\Programme\python\python\meineSkripte\Klasse 12\SQL_python_projekt.py", line 40, in mainmenu
    change(conn)
  File "F:\Informatik\Programme\python\python\meineSkripte\Klasse 12\SQL_python_projekt.py", line 87, in change
    changeSchueler(conn)
  File "F:\Informatik\Programme\python\python\meineSkripte\Klasse 12\SQL_python_projekt.py", line 274, in changeSchueler
    changeNN(conn)
  File "F:\Informatik\Programme\python\python\meineSkripte\Klasse 12\SQL_python_projekt.py", line 288, in changeNN
    showSchueler(conn, s)
  File "F:\Informatik\Programme\python\python\meineSkripte\Klasse 12\SQL_python_projekt.py", line 168, in showSchueler
    schuelers = c.execute('''SELECT * FROM Schueler WHERE schuelernr = ?''', (s)).fetchall()
ValueError: parameters are of unsupported type
Danke für die Info, dass wurde mir dann wohl mal falsch von meinem ehemaligen Lehrer gezeigt...
pleasehelp!
User
Beiträge: 28
Registriert: Donnerstag 15. November 2018, 20:44

Hallo, also habe jetzt versucht die Fragestellung auszulagern, allerdings bekomme ich diese Fehlermeldung!

Code: Alles auswählen

Traceback (most recent call last):
  File "F:\Informatik\Programme\python\python\meineSkripte\Klasse 12\SQL_python_projekt.py", line 442, in <module>
    mainmenu(conn)
  File "F:\Informatik\Programme\python\python\meineSkripte\Klasse 12\SQL_python_projekt.py", line 40, in mainmenu
    change(conn)
  File "F:\Informatik\Programme\python\python\meineSkripte\Klasse 12\SQL_python_projekt.py", line 87, in change
    changeSchueler(conn)
  File "F:\Informatik\Programme\python\python\meineSkripte\Klasse 12\SQL_python_projekt.py", line 276, in changeSchueler
    changeVN(conn)
  File "F:\Informatik\Programme\python\python\meineSkripte\Klasse 12\SQL_python_projekt.py", line 305, in changeVN
    c.execute('''UPDATE Schueler SET vorname = ? WHERE schuelernr = ?''', (VN, s))
NameError: name 's' is not defined
Es muss also iwo daran liegen...

Code: Alles auswählen

def changeVN(conn):
    c = conn.cursor()
    richtigeangabe(conn, changeVN)
    VN = input("Geben Sie den neuen Vornamen ein: ")
    c.execute('''UPDATE Schueler SET vorname = ? WHERE schuelernr = ?''', (VN, s))
    conn.commit() 
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Im ersten Fehler erwartet execute nunmal als zweiten Parameter etwas iterierbares und keine Zahl.

Und im zweiten Fehler, woher soll den s nun kommen? Ich finde es jedenfalls nicht.

Und Du solltest bei Deinen Variablennamen Dich endlich an die Konvention halten und Abkürzungen vermeiden.
pleasehelp!
User
Beiträge: 28
Registriert: Donnerstag 15. November 2018, 20:44

Also ich habe die Variablen vorgegeben und den Ausschnitt mit s hatte ich schon geschickt.

Code: Alles auswählen

def richtigeangabe(conn, funktion):
    while True:
        s = input("Geben Sie die Schülernummer ein: ")
        showSchueler(conn, s)
        print("Sind das die richtigen Schülerangaben?")
        WahlR = input("Ja oder Nein: ")
        WahlR = WahlR.lower()
        if WahlR == "ja":
            funktion
            break
        elif WahlR == "nein":
            pass
    return s
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Ja, aber Du weist den Rückgabewert von `richtigeangabe` in `changeVN` keiner Variable zu.
pleasehelp!
User
Beiträge: 28
Registriert: Donnerstag 15. November 2018, 20:44

Achso, wie mache ich das denn?
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Genauso, wie Du es an zwei anderen Stellen in der selben Funktion schon gemacht hast.
pleasehelp!
User
Beiträge: 28
Registriert: Donnerstag 15. November 2018, 20:44

Ok, wusste nicht, dass man das noch zuordnen muss. Vielen Dank, dann ist nurnoch meine Frage ob jemand eine Idee hat, wie man einen Teil ändern könnte, sodass ich nicht ganz viele Change Funktionen habe, sondern nur eine dann mit Variablen.
Antworten