Sqlite executemany wie debugen

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
diablo75
User
Beiträge: 30
Registriert: Dienstag 8. September 2009, 23:12

Hallo Leute,
hab ein kleines Problem.

Code: Alles auswählen

 def VertragInDbInsert (self, My_List):
        try:
            self.conn = sqlite3.connect('verstest.db')

            for element in My_List:
                self.conn.execute("""DELETE FROM VERTRAG WHERE Polizzennr='""" + element[1] + """'""")

            self.conn.executemany("""INSERT INTO VERTRAG(VUNr, Polizzennr, VertragsID, Vermnr, VtgProdCd, VtgProdukt,
                                  VtgSparteCd, ZahlRhythmCd, ZahlWegCd, VtgStatusCd, VtgStatusBeg, VtgBeg, VtgEnd, Hptfaelligkeit,
                                  DurchfDat, GueltigBeg, AendGrundCd, Aenderungsgrundbez, PraemieNtoVtg, PraemieBtoVtg,
                                  WaehrungsCd, BLZ, Ktonr, BIC, IBAN) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
                                  , ?, ?, ?, ?, ?, ?, ?, ?)""",My_List)

            #Änderungen durchführen
            self.conn.commit()

        except sqlite3.OperationalError as e:
            print('Fehler in OMDSVertrag-Insert in Vertrag (sqlite3) 01 : ' + e.args[0])

        finally:
            self.conn.close()
In My_List stecken 191 Datensätze in der DB sind dann aber nur 119.
Wie kann ich hier testen, warum manche Daten nicht in die DB eingtragen werden (Exception schmeißt er keine)???
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

In Deinem anderen Thread wurde Dir ja schon gesagt, dass man keine Daten in SQL-Strings einbaut, sondern Platzhalter verwendet.
Methoden und Variabelnamen schreibt man nach Konvention komplett klein. Ein My-Präfix ist nie sinnvoll, weil es keinen Mehrwert bietet und List ist zu generisch, so dass ein Variablenname my_list keinerlei Information über den Verwendungszweck liefert. `polizzen` wäre besser.
Auch Feldnamen in Tabellen sollten sprechend sein und keine kryptischen Abkürzungen enthalten. vtgprodcd???
Es ist unerwartet, dass eine Methode vertrag_in_db_eintragen das Attribut self.conn setzt. Es macht hier auch gar keinen Sinn, ein Attribut zu benutzen, da die Datenbank in der selben Methode wieder geschlossen wird.
Auch wenn die sqlite3-Anbindung `execute´ auf der Connection erlaubt, sollte man auch hier einen Cursor erstellen.

Woran erkennst Du, dass nicht alle Datensätze eingetragen worden sind?
Du kannst ja einfach per SELECT die Daten wieder abfragen, dann müßte ja klar sein, was eingetragen worden ist und was nicht.

Um Fehlersuche betreiben zu können, müßten wir wissen, wie die Datenbank-Tabelle vor dem Aufruf aussieht , wie die Daten und wie die Tabelle nach dem Aufruf?
diablo75
User
Beiträge: 30
Registriert: Dienstag 8. September 2009, 23:12

Ich öffne die DB mit einem Datenbankbrowser und schaue mir die Daten von Vertrag an. Da sind eben die besagten 119 Datensätze enthalten.
Wenn ich aber beim Debugen die Daten meiner List anschaue sehe ich 191.

Sollte nicht eine Fehlermeldung kommen wenn er das Insert nicht ausführen kann?
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Was sagt denn:

Code: Alles auswählen

 def VertragInDbInsert (self, polices):
        try:
            conn = sqlite3.connect('verstest.db')
            print(f"Liste: {len(polices)}")
            print(f'DB 1: {conn.execute("SELECT COUNT FROM VERTRAG").fetchall()}')
            for police in polices:
                conn.execute("DELETE FROM VERTRAG WHERE Polizzennr=?", (police[0]))
            print(f'DB 2: {conn.execute("SELECT COUNT FROM VERTRAG").fetchall()}')
            conn.executemany("""INSERT INTO VERTRAG(VUNr, Polizzennr, VertragsID, Vermnr, VtgProdCd, VtgProdukt,
                                  VtgSparteCd, ZahlRhythmCd, ZahlWegCd, VtgStatusCd, VtgStatusBeg, VtgBeg, VtgEnd, Hptfaelligkeit,
                                  DurchfDat, GueltigBeg, AendGrundCd, Aenderungsgrundbez, PraemieNtoVtg, PraemieBtoVtg,
                                  WaehrungsCd, BLZ, Ktonr, BIC, IBAN) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
                                  , ?, ?, ?, ?, ?, ?, ?, ?)""", polices)

            #Änderungen durchführen
            print(f'DB 3: {conn.execute("SELECT COUNT FROM VERTRAG").fetchall()}')
            conn.commit()

        except sqlite3.OperationalError as e:
            print('Fehler in OMDSVertrag-Insert in Vertrag (sqlite3) 01 : ' + e.args[0])

        finally:
            conn.close()
Ich habe mich mal bemüht bei der Gelegenheit deine kaputte Namensgebung zu korrigieren.

Das ist natürlich ungetestet.
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@sparrow: Das löschen enthält zwei Fehler: Die Klammern machen kein Tupel (aus dem Grund verwende ich lieber Listen, weil man dann das einsame Komma nicht braucht in dem Sonderfall wenn man nur einen Wert hat.

Und die Policenummer ist das zweite Argument in den Daten und nicht das erste.

@diablo75: Soll denn tatsächlich gelöscht werden? Oder würde ein UPDATE der vorhandenen Datensätze nicht eventuell effizienter sein?

Auch beim Löschen würde ich `executemany()` nehmen.

Gibt es irgendwelche Constraints? Kann es sein, dass es wertgleiche Datensätze gibt?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
diablo75
User
Beiträge: 30
Registriert: Dienstag 8. September 2009, 23:12

Ok danke werde ich morgen mal testen bzw. anschauen
diablo75
User
Beiträge: 30
Registriert: Dienstag 8. September 2009, 23:12

__blackjack__ hat geschrieben: Donnerstag 9. Juni 2022, 17:00 @diablo75: Soll denn tatsächlich gelöscht werden? Oder würde ein UPDATE der vorhandenen Datensätze nicht eventuell effizienter sein?
so hab ich es Anfangs gemacht aber dann geändert weil ich dann noch div. Abfragen machen muss (ob PolNr. schon vorhanden usw.) daher lösch ich und trag den Datensatz neu ein.
__blackjack__ hat geschrieben: Donnerstag 9. Juni 2022, 17:00 Gibt es irgendwelche Constraints? Kann es sein, dass es wertgleiche Datensätze gibt?
Jeder Datensatz sollte in Vertrag nur 1x vorkommen. Werd ich aber sicherheitshalber nochmals überprüfen.
diablo75
User
Beiträge: 30
Registriert: Dienstag 8. September 2009, 23:12

sparrow hat geschrieben: Donnerstag 9. Juni 2022, 16:36 Was sagt denn:

Code: Alles auswählen

 def VertragInDbInsert (self, polices):
        try:
            conn = sqlite3.connect('verstest.db')
            print(f"Liste: {len(polices)}")
            print(f'DB 1: {conn.execute("SELECT COUNT FROM VERTRAG").fetchall()}')
            for police in polices:
                conn.execute("DELETE FROM VERTRAG WHERE Polizzennr=?", (police[0]))
            print(f'DB 2: {conn.execute("SELECT COUNT FROM VERTRAG").fetchall()}')
            conn.executemany("""INSERT INTO VERTRAG(VUNr, Polizzennr, VertragsID, Vermnr, VtgProdCd, VtgProdukt,
                                  VtgSparteCd, ZahlRhythmCd, ZahlWegCd, VtgStatusCd, VtgStatusBeg, VtgBeg, VtgEnd, Hptfaelligkeit,
                                  DurchfDat, GueltigBeg, AendGrundCd, Aenderungsgrundbez, PraemieNtoVtg, PraemieBtoVtg,
                                  WaehrungsCd, BLZ, Ktonr, BIC, IBAN) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
                                  , ?, ?, ?, ?, ?, ?, ?, ?)""", polices)

            #Änderungen durchführen
            print(f'DB 3: {conn.execute("SELECT COUNT FROM VERTRAG").fetchall()}')
            conn.commit()

        except sqlite3.OperationalError as e:
            print('Fehler in OMDSVertrag-Insert in Vertrag (sqlite3) 01 : ' + e.args[0])

        finally:
            conn.close()
Ich habe mich mal bemüht bei der Gelegenheit deine kaputte Namensgebung zu korrigieren.

Das ist natürlich ungetestet.
Anscheinend muss ich wo anders in meinem Programm den Fehler suchen.
Hier die Ausgabe:
Person einspielen gestartet .....
Person einspielen beendet (204 Personen eingespielt)
Lese Verträge ein...
Liste: 191
DB 1: [(0,)]
DB 2: [(0,)]
DB 3: [(191,)]
Vertrag einspielen beendet (191 eingespielt)
Person einspielen gestartet .....
Person einspielen beendet (0 Personen eingespielt)
Lese Verträge ein...
Liste: 0
DB 1: [(119,)]
DB 2: [(119,)]
DB 3: [(119,)]
Vertrag einspielen beendet (0 eingespielt)
diablo75
User
Beiträge: 30
Registriert: Dienstag 8. September 2009, 23:12

Ok habs gefunden. (in einer anderen Funktion habe ich Verträge gelöscht statt ein bestimmtes Unterelement) :-)
Ich sollte mehr bei Copy Paste aufpassen.
Antworten