Seite 1 von 1

SQLite Update mit Variable aus SELECT SUM(Spalte)

Verfasst: Freitag 10. November 2023, 16:59
von KaKri
Als Python-Anfänger teste ich die Einbindung von Excel und SQLite in ein Python-Programm. Excel funktioniert, auch SQLite arbeitet bis ein ein Problem einwandfrei:

Ich summiere alle Werte einer Tabelle, das Resultat möchte ich in einer andere Tabelle speichern.

01 import sqlite3
02 import pandas as Pd
03
04 Datenbank = "G:\\Python\\Database.db"
05 verbindung = sqlite3.connect(Datenbank)
06 zeiger = verbindung.cursor()
07
08 zeiger.execute("SELECT SUM(Betrag) FROM Buchungen WHERE Bank = 'BA'")
09 results = list(zeiger)
10 fWert = results
11
12 print(fWert)
13
14 Konto = "BA"
15
16 zeiger.execute("UPDATE Konten SET Saldo = ? WHERE Konto = ?", (fWert, cKonto))
17
18 verbindung.commit()

Die Variable "fWert" wird immer mit einem "," am Ende angezeigt: [(16945.230000000338,)] gefolgt von der Fehlermeldung:

"Traceback (most recent call last):
File "g:\Python\KK-Finanzen\Excel-to-SQL.py", line 16, in <module> zeiger.execute("UPDATE Konten SET Saldo = ? WHERE Konto = ?", (fWert, cKonto))
sqlite3.ProgrammingError: Error binding parameter 1: type 'list' is not supported"

Wenn ich die Variable "fWert" mit einer Zahl manuell fülle, funktioniert alles bestens.

Wie kann ich das aus dem SUM resultierende Ergebnis in eine verwertbare Zahl konvertieren? Habe schon alle im Web gefundenen Lösungsvorschläge versucht, bisher leider kein Erfolg. Wahrscheinlich übersehe ich nur eine Kleinigkeit, aber wie schon erwähnt: Bin blutiger Anfänger!

Im Voraus vielen Dank für eure Hilfe.

Re: SQLite Update mit Variable aus SELECT SUM(Spalte)

Verfasst: Freitag 10. November 2023, 19:17
von noisefloor
Hallo,

wie du das Ergebnis abholst ist... komisch. Die Python DB 2.0 API - die du über das Python SQLite-Modul nutzt, kennen `fetchone()` zum Abholen von einem Abfrageergebnis, `fetchall` alle Ergebnisse. Siehe https://docs.python.org/3/library/sqlit ... r.fetchone.

In deinem Fall, wo ja ziemlich sicher nur ein Ergebnis zurück kommt, wäre `fetchone()` das Mittel der Wahl. `fetchone()` liefert als Ergebnis ein Tupel mit einem Element. Wie man darauf zugreift weißt du hoffentlich, weil das Python Grundlagen sind.

Dein Programm sieht dann aufgeräumt so aus - ungetestet:

Code: Alles auswählen

 import sqlite3

ACCOUNT = "BA"
DATABASE = "G:\\Python\\Database.db"
connection = sqlite3.connect(DATABASE)
cursor = connection.cursor()
result = cursor.execute("SELECT SUM(Betrag) FROM Buchungen WHERE Bank = 'BA'").fetchone()

cursor.execute("UPDATE Konten SET Saldo = ? WHERE Konto = ?", (result[0], ACCOUNT))
cursor.commit()
Abgesehen davon: wenn du den Saldo in der DB speicherst hast du die Daten quasi doppelt in der DB. Du kannst du Saldo ja jederzeit aus der DB berechnen. Davon ausgehen, dass die Tabelle "Buchungen" auch das Datum der Buchung enthält. Das speichern des Saldo ist nicht per se falsch, kann aber überflüssig im Sinne von doppelt gemoppelt sein.

Gruß, noisefloor

Re: SQLite Update mit Variable aus SELECT SUM(Spalte)

Verfasst: Freitag 10. November 2023, 22:31
von __blackjack__
@KaKri: noisefloor hat die Namen schon ”konventionalisiert”, ohne das zu kommentieren: Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

Namen sollten keine kryptischen Abkürzungen enthalten. Und auch keine Grunddatentypen. In Kombination wird es nicht besser. Also kein `fWert` und kein `cKonto`. Die Datentypen ändert man im Laufe der Entwicklung gerne mal zu etwas spezifischerem, teilweise selbst geschrieben, und dann hat man falsche, irreführende Namen im Programm oder muss alle betroffenen Namen ändern. Der Wert könnte Beispielsweise auch `decimal.Decimal` sein statt `float`, weil das viele Datenbankanbindungen für die NUMERIC-Typen in SQL verwenden wenn dort eine feste Anzahl von Nachkommastellen deklariert ist.

Und das schliessen von Verbindung und Cursor sollte man sicherstellen:

Code: Alles auswählen

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

ACCOUNT = "BA"
DATABASE = R"G:\Python\Database.db"


def main():
    with closing(sqlite3.connect(DATABASE)) as connection:
        with closing(connection.cursor()) as cursor:
            cursor.execute(
                "SELECT SUM(betrag) FROM buchungen WHERE bank = 'BA'"
            )
            cursor.execute(
                "UPDATE konten SET saldo = ? WHERE konto = ?",
                (cursor.fetchone()[0], ACCOUNT),
            )
            cursor.commit()


if __name__ == "__main__":
    main()

Re: SQLite Update mit Variable aus SELECT SUM(Spalte)

Verfasst: Samstag 11. November 2023, 10:21
von KaKri
Vielen Dank für die prompten Hilfen. Das Problem ist damit behoben. Die sonstigen Empfehlungen sind für mich als Anfänger sehr wertvoll.

Liebe Grüße

Re: SQLite Update mit Variable aus SELECT SUM(Spalte)

Verfasst: Dienstag 14. November 2023, 18:01
von bb1898
noisefloor hat geschrieben: Freitag 10. November 2023, 19:17

Code: Alles auswählen

 import sqlite3

ACCOUNT = "BA"
...
result = cursor.execute("SELECT SUM(Betrag) FROM Buchungen WHERE Bank = 'BA'").fetchone()

cursor.execute("UPDATE Konten SET Saldo = ? WHERE Konto = ?", (result[0], ACCOUNT))
cursor.commit()
Zweierlei kommt mir auch hier noch seltsam vor:

Was ist "BA" denn nun? Die Bank oder das Konto bei der Bank?

Und, wichtiger: wieso wird im ersten SELECT der Parameter 'BA' direkt hineingeschrieben - was man bekanntlich nicht tut? Im UPDATE-Befehl ist es ja auch richtig gemacht.

Re: SQLite Update mit Variable aus SELECT SUM(Spalte)

Verfasst: Dienstag 14. November 2023, 20:25
von noisefloor
Hallo,
Und, wichtiger: wieso wird im ersten SELECT der Parameter 'BA' direkt hineingeschrieben - was man bekanntlich nicht tut?
Die Aussage ist in der Pauschalität falsch. Wer sagt denn, dass die Bank (mal davon ausgehen, das "BA" das Kürzel für eine Bank ist) ein variables Parameter ist? Vielleicht gibt des den Query nur mit "BA". Dann ist das vollkommen ok so.

Es liegt zwar Vermutung nahe, dass das vielleicht je nach Entwicklung des Programms, zu einem Parameter werden könnte. Wissen wir aktuell aber nicht und wir kennen aktuell auch nicht das ganze Programm.+

Gruß, noisefloor