Select nach Datum--- Probleme

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
fatboy05
User
Beiträge: 1
Registriert: Donnerstag 25. Februar 2016, 10:30

Hallo zusammen,

zuerst möchte ich mich kurz Vorstellen. Mein Name : Uwe, Alter 62, Rentner, Hobbies: Ski, Moped, Aquarium (Südamerika), Haussteuerung( mit Raspberry).

Ich bastle gerade an einer Weboberfläche mit der ich Rolladen auf/zu fahren möchte, licht schalten, Garagentor usw, Aquariensteuerung (Temperatur, LED, Wasserwechsel)
Im Augenblick läuft dieses noch auf zwei Siemens Logo, Möchte es aber auf Raspi umstellen.

Weboberfläche habe ich schon etwas, kann im Garten Lampen schalten, Garagentor auf und zu fahren.

Nun komme ich zu meinem Problem:

ich sammle Temperatur Daten von 9 Sensoren (DS 1820) und schreibe die Daten alle 15 min in einer Mysql Datenbank.
Diese Daten möchte ich jeden Tag um ca 00:01 in MAX, MIN und AVG (für jeden Tag zusammen fassen) in einem anderen Table schreiben.

Dabei habe ich mit dem Datum ein Verständnis Problem. (bin schon mehrere Tage dran, um das Problem zu lösen)

Wenn ich es so schreibe funktioniert es prima.
Wobei Date ein Timestamp ist.
und daten31 die Temperatur Daten für den laufenden Monat enthalten soll. ( im Augenblick aber seit November 2015 bis Heute)

cursor.execute("""SELECT * FROM daten31 WHERE year(Date) = '2015' AND month(Date) = '11' AND day(Date) = '30' """)

aber ich möchte ja anstatt mit festen Zahlen abfragen, Variablen nehmen!

jahr = "2015"

cursor.execute("""SELECT * FROM daten31 WHERE year(Date) = 'jahr' AND month(Date) = '11' AND day(Date) = '30' """)

und das geht schief??? aber warum, verstehe ich nicht.

Fehlermeldung:

v_daten31_n_history.py:29: Warning: Truncated incorrect DOUBLE value: 'jahr'
cursor.execute("""SELECT * FROM daten31 WHERE year(Date) = 'jahr' AND month(Date) = '11' AND day(Date) = '30'""")


lg Uwe
BlackJack

@fatboy05: Du versuchst 'jahr' in SQL als Zahl zu verwenden, das ist aber eine Zeichenkette. Und hat überhaupt nichts mit der Python-Variable mit dem Namen `jahr` zu tun. Wie sollte es auch? Woher sollte die `execute()` Methode wissen das ausgerechnet dieser Wert nicht als SQL gemeint ist sondern Du gerne hättest das dort der Wert einer Python-Variable eingesetzt werden soll, von der die `execute()`-Methode auch gar nichts weiss, denn die wurde ihr ja nicht übergeben? Erwartest Du das die Methode irgendwo im Namensraum des Aufrufers nachschaut ob dort gewollt oder zufällig Namen existieren die Zeichenketten im SQL entsprechen und die dann auf magische Weise ersetzt?

Du müsstest im SQL entsprechende Platzhalter für Werte verwenden und die dann als zweites Argument an `execute()` übergeben.

Achtung: Auf keinen Fall Werte mit Zeichenkettenoperationen in die Zeichenkette mit der SQL-Anweisung hinein formatieren! Das ist im besten Fall ineffizienter und eine Fehlerquelle und im schlechtesten Fall eine Sicherheitslücke (SQL-Injection).

Der Tabellenname `daten31` ist komisch‽ Gibt es noch andere Nummern? Wofür stehen die? Kann es sein dass Du da Werte in Tabellennamen kodierst die eigentlich in Tabellen gehören?

Ist die Tabelle mit den aggregierten Werten tatsächlich nötig? Datenbanken sind eigentlich gut darin Abfragen zu beantworten, so dass man eigentlich nicht selber anfangen sollte Datenbankergebnisse in der Datenbank zu cachen. Wenn man so eine Tabelle benötigt, bietet sich vielleicht auch ein View statt einer ”echten” Tabelle an.

Den ``*`` beim SELECT sollte man vermeiden und explizit hin schreiben welche Spalten man abfragen möchte. Das dokumentiert den Quelltext weil der Leser auch ohne den Datenbankentwurf im Kopf zu haben sieht was dort abgefragt wird. Und es macht das Programm robuster gegen Änderungen im Schema, beispielsweise hinzukommende, entfernte, oder umsortierte Spalten.
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

fatboy05 hat geschrieben:

Code: Alles auswählen

jahr = "2015" 
cursor.execute("""SELECT * FROM daten31 WHERE year(Date) = 'jahr' AND month(Date) = '11' AND day(Date) = '30' """)
Weder Python noch die Datenbank ersetzen auf magische Art und Weise irgendwelche Textinhalte einer Query durch Werte im Python-Skript die möglicherweise einen gleichlautenden Bezeichner haben. Für so etwas gibt es Platzhalter.

Schau dir mal die Dokumentation der exceute-Methode für SQLite an.

Andere Datenbanken verwenden möglicherweise andere Platzhalter, wie z.B. %s bei MySQL (wenn ich mich recht erinnere).

(EDIT: Oh, Beitrag Nummer 3000 für mich)
Benutzeravatar
miracle173
User
Beiträge: 127
Registriert: Samstag 6. Februar 2016, 00:28

Man kann Bind-Variable verwenden. Die leisten das, was du vermutlich erreichen wolltest.

Code: Alles auswählen

jahr = "2015" 
cursor.execute(
    "SELECT * "
    " FROM daten31"
    " WHERE year(Date) = :bvJahr"
    " AND month(Date) = '11'"
    " AND day(Date) = '30'",
    {"bvJahr",jahr})
sqlite3.Cursor.execute(sql[, parameters])




 
Antworten