Seite 1 von 2

seltsame Fehlermeldung in sqlite3

Verfasst: Samstag 5. Januar 2019, 18:19
von Cortez
Hallo,

ich habe folgendes kleine Skript geschrieben (eine kleine Datenbank in sqlite3, die Personendaten speichern kann). Leider bekomme ich, nachdem ich einen datensatz eingegeben habe, stets folgende Fehlermeldung:

Traceback (most recent call last):
File "./verwaltung.py", line 46, in <module>
personaldateneingeben(id, name, vorname, anschrift, telefon, mail)
File "./verwaltung.py", line 21, in personaldateneingeben
VALUES(?,?,?,?,?,?) """, (id, name, vorname, anschrift, telefon, mail))
sqlite3.InterfaceError: Error binding parameter 0 - probably unsupported type
.

Das Verrückte ist, dass das Ganze jedoch wunderbar funktioniert hat, bis ich das Auswahlmenü am anfang programmiert habe - Dateneingabe oder Programmende. Warum geht das jetzt nicht mehr?
Bin um jeden Tipp dankbar.

Code: Alles auswählen

#!/usr/src/Python-3.7.2/python

import sqlite3

datenbank = sqlite3.connect('verwaltung.db')
print ("Datenbank geöffnet")


datenbank.execute(""" CREATE TABLE IF NOT EXISTS Personen (
        ID INT PRIMARY KEY NOT NULL,
        NAME TEXT NOT NULL,
        VORNAME TEXT NOT NULL,
        ANSCHRIFT TEXT,
        TELEFON TEXT,
        MAIL TEXT)""")


def personaldateneingeben(id, name, vorname, anschrift, telefon, mail):
    
    datenbank.execute (""" INSERT INTO Personen(ID, NAME, VORNAME, ANSCHRIFT, TELEFON, MAIL)
        VALUES(?,?,?,?,?,?) """, (id, name, vorname, anschrift, telefon, mail))
  
    datenbank.commit()
 
print ("Was möchten Sie tun")
print()
print("Daten anlegen=1")
print()
print("Programmende=2")
print()


while True:
    
    eingabe = input ("Bitte eingeben ")
    if eingabe == "1":
        i = 1
        while True:
            print()
            name = input ("bitte Zunamen eingeben")
            vorname = str(input ("bitte Vornamen eingeben"))
            anschrift = str(input("bitte Anschrift eingeben oder [Enter], falls unbekannt"))
            telefon = str(input("bitte Telefonnummer eingeben oder [Enter], falls unbekannt"))
            mail = str(input("bitte mailadresse angeben oder [Enter],falls unbekannt"))

            personaldateneingeben(id, name, vorname, anschrift, telefon, mail)
            print()
            eingabe = input("Noch eine Person anlegen? [j] oder [n]")

            if eingabe == "j":
                id=int(id)+1
            elif eingabe == "n":
                break
            else:
             #eingabe2 =  input("Bitte [j] oder [n] eingeben")
                while True:
                    eingabe2 =  input("Bitte [j] oder [n] eingeben")
                    if eingabe2 == "j":
                        id=int(id)+1
                        break
                    if eingabe2 == "n":
                        break
                if eingabe2 == "n":
                    break
        
    if eingabe == "2":
        print ("Auf Wiedersehen")
        break
    
datenbank.close()

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Samstag 5. Januar 2019, 18:27
von Sirius3
`id` ist die eingebaute id-Funktion, die Du natürlich nicht in eine Datenbank schreiben kannst.

Auch wenn SQLite das zuläßt, sollte man sich trotzdem einen Cursor erzeugen, auf dem man `execute` aufruft. Funktionen sollten alles was sie brauchen über ihre Argumente bekommen, also auch `datenbank`.
Die ganzen `str`-Aufrufe sind überflüssig und können weg.
Irgendwie sind die vielen verschachtelten while-Schleifen zu verschachtelt, da ist ein bißchen doppelter Code drin.

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Samstag 5. Januar 2019, 19:21
von __blackjack__
Cortez: Warum schreibst Du die Spaltennamen im SQL alle GROSS? Wenn man die klein schreibt, lassen sie sich deutlich leichter von den Datentypen und anderen SQL-Schlüsselwötern unterscheiden.

Das NOT NULL beim PRIMARY KEY ist überflüssig.

Die ID braucht man dann auch gar nicht mehr selbst angeben, da kümmert sich SQLite schon drum.


Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. Dannistmanauchgezwungen`datenbank`alsArgumentandie`personaldateneingeben()`-Funktionzuübergeben. Liest sich blöd ohne Leerzeichen? Funktionsnamen ohne Unterstriche zwischen den Worten auch. ;-)

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Sonntag 6. Januar 2019, 00:11
von Cortez
Danke erstmal für die, wie immer, rasche und kompetente Hilfe.

Habe den Fehler gefunden.
@Black_Jack: Ich habe irgendwie fälschlicherweise gedacht, dass sql-Spalten großgeschrieben werden müssen. Naja habs abgeändert. :)

Stehe jetzt allerdings vor einem Problem, bei dem ihr mir vielleicht auch helfen könnt:

Und zwar würde mich interessieren, ob man Tabellenspalten auch dynamisch(vielleicht der falsche Ausdruck) befüllen kann.

Nehmen wir an, ich hätte eine Tabelle mit 10 Spalten, von denen aber nicht immer alle befüllt werden sollen (in unserem Beispiel könnte das eine Faxnummer oder 2. Mailadresse sein, was eventuell nicht jeder hat). Kann ich das dem Skript irgendwie geschickt klarmachen?

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Sonntag 6. Januar 2019, 00:29
von Sirius3
Für die fehlenden Werte übergibst Du einfach None.

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Sonntag 6. Januar 2019, 12:46
von Cortez
Danke dir für den Tipp.

Kann ich diese None-Werte dann auch aus der Datenbank lesen um im Programm damit arbeiten zu können (also mit Schleifen oder Ähnlichem) - z.B. dass die Schleife überspringt, wenn ein leerer Wert erscheint

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Sonntag 6. Januar 2019, 13:05
von sls
Cortez hat geschrieben: Sonntag 6. Januar 2019, 12:46 Kann ich diese None-Werte dann auch aus der Datenbank lesen um im Programm damit arbeiten zu können (also mit Schleifen oder Ähnlichem) - z.B. dass die Schleife überspringt, wenn ein leerer Wert erscheint
Ja, Datenbanken behandeln diesen Wert i.d.R. immer als NULL, was äquivalent zu Python's None ist.

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Sonntag 6. Januar 2019, 13:33
von __blackjack__
@Cortez: Wobei man natürlich auch gleich die Datenbankabfrage so gestalten kann, das die Werte gar nicht erst geliefert werden wenn man sie im Programm sowieso nur überspringen würde.

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Sonntag 6. Januar 2019, 13:35
von snafu
Sirius3 hat geschrieben: Samstag 5. Januar 2019, 18:27 `id` ist die eingebaute id-Funktion, die Du natürlich nicht in eine Datenbank schreiben kannst.
Nicht wirklich. id wird durch den Funktionsparameter überschrieben und hält somit das, was der Funktion an dieser Stelle übergeben wurde. Ratsam ist das Überschreiben eingebauter Funktionen natürlich trotzdem nicht, wobei ich es im Falle von id schon öfter gesehen habe.

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Sonntag 6. Januar 2019, 13:42
von __blackjack__
@snafu: Doch wirklich, denn der Funktion wird als erstes Argument die eingebaute `id()`-Funktion übergeben. :-)

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Sonntag 6. Januar 2019, 20:23
von Cortez
Ok, eure Antworten haben bei mir jetzt einige Unklarheiten hervorgerufen.

Ich versuche mal zu erklären, was ich gerne möchte:

Sagen wir mal, ich habe eine Tabelle mit 10 Feldern. Davon werden nicht immer alle Felder befüllt (hängt von der Zeile ab).
Mein Programm fragt per Schleife den Benutzer nach den werten (wenn ein Feld leer bleibt, soll er halt enter oder so drücken). Die Werte werden dann in eine Liste gespeichert und in die Tabelle eingetragen.

So, wie krieg ich das mit dem Null setzen nun am Besten hin? Meine Idee wäre folgende: der Liste halt überall da, wo nix vom User eingegeben wurde, den Wert Null geben. Und danach irgendwie Query (muss mich noch schlau machen, ob und wie das geht) starten, wo eben alle Werte, die 0 sind, gefunden und gelöscht werden.
Ist das ein praktikabler Weg oder, wie man sagt, mit Kanonen nach Spatzen geschossen?
Sorry für die dummen Fragen, aber mein sqlite-Wissen beschränkt sich auf das, was youtube-Tutorials so hergeben...

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Sonntag 6. Januar 2019, 20:35
von __blackjack__
@Cortez: Da wo der Benutzer nichts angegeben hat verwendest Du `None` als Wert. Und bei der Abfrage bekommst Du überall wo Du `None` angegeben hast – man glaubt es kaum – `None` als Wert aus der Datenbank. Ich verstehe jetzt nicht so ganz welches Problem Du damit hast?

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Sonntag 6. Januar 2019, 21:56
von Cortez
Ich habe fürmein Anliegen mal ein vereinfachstes Skript geschrieben (Prinzip ist aber dasGleiche)

Code: Alles auswählen

import sqlite3

db = sqlite3.connect('Testdatenbank')

db.execute(""" CREATE TABLE IF NOT EXISTS Werte (
        Wert1 INT,
        Wert2 INT,
        Wert3 INT,
        Wert4 INT,
        Wert5)""")

i = 1
Werteliste = []
While i < 6:
    var = input(" Bitte Wert eingeben")
    if var == "Abbruch":
        break
    elif var == " ":
        Werteliste.append(0)
    else:
        Werteliste.append(var)
    i = i+1
    
db.execute(""" INSERT INTO Werte(Wert1, Wert2, Wert3, Wert4, Wert5) VALUES(?,?,?,?,?) """, (Werteliste[0], Werteliste[1], Werteliste[2], Werteloiste[3], Werteliste[4]))

db.close()

Also ich kriegs irgendwie nicht hin, anstelle den 0-Werten in der Liste dann None zu übermitteln.

By the way: Falls ein Benutzer nun mehr als 5 Werte eingeben wollte - kann sqlite3 in solch einem Fall auch dynamisch neue Felder hinzufügen oder muss man das bei der Tabellenerstellung schon machen und danach geht nichts mehr?

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Sonntag 6. Januar 2019, 22:25
von Sirius3
Warum ist Wert5 kein INT? Und warum schreibst Du dann nur Texte in die Datenbank? 0 ist nicht None. Wenn Du Abbruch eingibst, dann ist die Liste zu kurz und es gibt später Fehler. Die while-Schleife sollte mit kleinem w geschrieben werden und besser eine for-Schleife sein.
Und nein, ein Datenbankschema ist fix. Aber das Beispiel hat auch nichts mit Deinem vorherigen Problem zu tun.

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Sonntag 6. Januar 2019, 22:56
von Cortez
Ja, wert5 soll auch ein int sein. Und im fertigen Programm läuft noch einmal eine Schleife, die überall da, wo noch kein Wert ist, auch eine 0 einfügt.
Dass 0 nicht NONE ist, ist mir klar. Und das ist ja das Problem. Ich möchte, dass die Zahlen in die Tabelle werden, eben außer da, wo aufgrund fehlender Nutzereingaben der Liste eine 0 gegeben wurde. Und in der Tabelle sollen diese Nuller zugunsten des Leerwertes NONE getauscht werden. Und ich weiß nicht wie. Feldernamen können ja nicht als Variablen an den SQL-Befehl übergeben werden - sonst wärs mit Schleife einfach.

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Sonntag 6. Januar 2019, 23:36
von Sirius3
Ein Leerwert ist nicht 0 sondern None. Warum willst Du dann eine 0 schreiben? Und ohne alles auszulesen, weißt Du ja nicht, ob da None oder nicht in der Stelle steht.

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Sonntag 6. Januar 2019, 23:47
von __blackjack__
Das heisst `None` in Python und nicht `NONE`. Und in der Datenbank wird Python's `None` auf den SQL-Wert `NULL` abgebildet.

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Montag 7. Januar 2019, 06:50
von sparrow
Wenn du dynamisch Spalten an eine SQL-Tabelle einfügen möchtest, ist entwededer das Design der Dstenbank falsch oder du benutzt das falsche Werkzeug.
Nur weil die Dinger "Tabellen" heißen, hat das nichts mit Tabellenkalkulation zu tun.

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Montag 7. Januar 2019, 18:24
von Cortez
Ok, ich glaube, wir reden irgendwie aneinander vorbei 😊

Nehmen wir an, der User gibt für den ersten Datensatz die Werte 1,2,3,4,5 ein. Dann steht in der Tabelle 1 2 3 4 5. Weil eben alle Werte eingeben wurden und die Liste voll ist.

So, für den zweiten Datensatz gibt er dann ein: 1, 2, , 4, 5. Für die Spalte3 hat er also keinen Wert eingeben, aber das Skript schreibt dafür eine 0, damit die Liste richtig befüllt ist. In der Tabelle steht dann also 1,2,0,4,5

Für den dritten Datensatz wird dann z.B. 1,2,3, , , eingegeben. In der Tabelle steht daher 1,2,3,0,0.

Wie krieg ich die Nullen dann aus der Tabelle raus, dass die Spalten dann überall da, wo mein Skript die 0 übertrug, wirklich leer sind? Weil so ist ja die einzige Möglichkeit, da anders, wie gesagt, in Beispiel 3 z.B. ein put of index Error oder sowas kommt?

Ich muss das Ganze so umständlich machen, weil man ja dynamisch keine Spalten dazufügen kann. Dann muss man eben soviel Spalten anlegen, dass die maximale Anzahl an Werten, die der User eingeben könnte, nicht überschritten wird.

Oder gibts da doch irgendwas, was einfacher und effektiver ist?

Re: seltsame Fehlermeldung in sqlite3

Verfasst: Montag 7. Januar 2019, 18:37
von __deets__
Du *musst* ueberhaupt keine 0 in die DB schreiben. Denn das ist eine gueltige Zahl, warum soll die NICHT eingebbar sein? Und wenn es ok ist, dass sie von Seitens des Benutzers signalisiert, dass eben keine Eingabe erfolgen soll (statt dem viel sinnvolleren "nur-return-druecken") - dann ist das immer noch losgeloest davon, was DU in deinem Skript damit dann machst.

Code: Alles auswählen

wert = input() # eingabe '0'
if wert == '0':
      wert = None 
insert_into_datenbank(wert)
Und None ist das, was dann in der Datenbank NULL wird. NULL. Nicht 0. NULL kann man auch benutzen bei String-Spalten, oder allen anderen. Das hat NICHTS mit der Zahl 0 zu tun, sondern ist ein spezieller Wert, der sagt "hier ist nix". Und den setzt man von Python aus mit dem dort ebenso definierten Spezial-Wert None, und None ist auch was man bekommt, wenn man eine Zeile abfragt, in der ein NULL-Wert in der Datenbank steht.

Last but not least: natuerlich gibt es etwas, das effektiver ist: das anlegen einer 1:n-Tabelle, in der du pro Eintrag genau *EINE* Zahl ablegst. Damit bist du bei der Anzahl der Zahlen deiner Liste nicht durch eine feste Anzahl an Tabellen-Spalten festgelegt.