Seite 1 von 1
variable per UPDATE einfügen
Verfasst: Montag 5. Juni 2017, 14:53
von peko
Hallo zusammen,
meine Versuche einen UPDATE-Befehl an eine Sqlite DB zu senden, scheitern kläglich.
Code: Alles auswählen
zeit = time.strftime("%d%m%Y-%X")
cursor.execute("UPDATE tabname SET aktwert = '1', turn = zeit WHERE spalte = 17")
conn.commit()
Solange ich nur "feste Werte" wie z.B. "1" nehme, funktioiert das prächtig, aber mit der Variablen
zeit geht es überhaupt nicht.
Code: Alles auswählen
Fehlermeldung: sqlite3.OperationalError: no such column: zeit
Wobei die
zeit ja die Variable ist, die Spalte turn gibt es in der Sqlite Tabelle.
Was mache ich falsch?
Gruß
PeKo
Re: variable per UPDATE einfügen
Verfasst: Montag 5. Juni 2017, 15:16
von Melewo
So ähnlich vermutlich, wobei mir 'Zeit' noch nicht richtig formatiert erscheint.
So wie Du es versuchst einzufügen, wird Zeit wohl nur als String ausgewertet. Probiere einfach, bis es richtig passt.
Code: Alles auswählen
zeit = time.strftime("%d%m%Y-%X")
print("UPDATE tabname SET aktwert = '1', turn = '" + zeit + "' WHERE spalte = 17")
# Oder:
zeit = time.strftime("%d%m%Y-%X")
print("UPDATE tabname SET aktwert = '1', turn = '{0:1}' WHERE spalte = 17".format(zeit))
Re: variable per UPDATE einfügen
Verfasst: Montag 5. Juni 2017, 15:35
von __deets__
Du kanns nicht einfach einen Namen in dein SQL statement schreiben und hoffen, dass das durch ein Wert einer Variablen aus dem Kontext des Aufrufs ersetzt wird. Das wäre auch du ziemlich dramatisch, was würde passieren wenn du eine neue Variable anlegst, die zufällig gleich heißt wie eine Spalte?
Stattdesssen musst du den Wert an das execute übergeben, und dafür eigenen Platzhalter angeben im Statement. Leider hängt die konkrete Vorgehensweise von deiner datenbank ab, aber zB SQLite macht es so:
Code: Alles auswählen
cursor.execute("UPDATE Tabelle WHERE spalte = ?", (wert, ))
Der von melewo vorgeschlagene weg ist zu vermeiden, da er dich für SQL injection Angriffe anfällig macht, und außerdem spart man sich mit der von mir gezeigten parametrisierten Form eine Typwandlung - man kann einfach zB ints, floats, oder datetime Objekte übergeben.
Re: variable per UPDATE einfügen
Verfasst: Montag 5. Juni 2017, 16:17
von Melewo
Ja, ist richtig wie __deets__ es beschreibt mit ?, benutze ich im Web ebenfalls. Nur allgemein kommt mir die Formatierung von Zeit merkwürdig vor, würde eher dieses Schema erwarten, wenn es einem richtigen Datetime entsprechen soll:
'0000-00-00 00:00:00'
Kommt aber darauf an, wie Du Deine Datenbank eingerichtet hast.
Re: variable per UPDATE einfügen
Verfasst: Montag 5. Juni 2017, 16:49
von peko
Danke erstmal für die schnellen Antworten !
@ __deets__
Wenn ich es so schreibe:
Code: Alles auswählen
cursor.execute("UPDATE tabname WHERE spalte = ?", (17,'1',zeit))
oder auch
Code: Alles auswählen
cursor.execute("UPDATE tabname WHERE spalte = 17", ('1',zeit))
kommt immer folgender Fehler:
Klappt irgendwie nicht...
@ Melewo: es ist absichtlich kein richtiger Timestamp
Gruß
peko
Re: variable per UPDATE einfügen
Verfasst: Montag 5. Juni 2017, 16:52
von Sirius3
@peko: richtiges SQL wäre
Code: Alles auswählen
cursor.execute("UPDATE tabname SET aktwert = ?, turn = ? WHERE spalte = ?", ('1', zeit, 17))
Was ist der Sinn dahinter, absichtlich falsche Timestamps zu benutzen?
Re: variable per UPDATE einfügen
Verfasst: Montag 5. Juni 2017, 17:48
von peko
Danke Sirius3 !
So funktioniert es.
Das Zeitformat ist für ein anderes PHP Programm, welche auf die Datenbank zugreift und dieses Format so weiterverarbeitet.
Da will ich nichts dran ändern.
Gruß
peko
Re: variable per UPDATE einfügen
Verfasst: Sonntag 23. Juli 2017, 20:39
von nobby46
Hallo und guten Abend.
Ich mache meine ersten Gehversuche mit Python und SQL. Dabei habe ich ein Problem mit der Eingabe einer Variablen in eine DB.
Das erstellen CREATE TABLE und INSERT INTO habe ich hinbekommen. Nur komme ich nicht weiter mit UPDATE.
Hier ein Ausschnitt:
Code: Alles auswählen
test = 2
sql = """
UPDATE temperaturen SET fuehler = test WHERE id = 1
"""
conn.execute(sql)
Wenn ich anstelle der Variable test, einen Wert als Dezimalzahl z.B. 2 eingebe funktioniert es sauber.
Sonst bekomme ich die Meldung: OperationalError: no such column: test
Ich hoffe es kann mir jemand zeigen was ich falsch mache. Habe leider im Netz nichts gefunden. Hier geht man immer von Dezimalzahlen aus.
Norbert
Re: variable per UPDATE einfügen
Verfasst: Sonntag 23. Juli 2017, 21:11
von __deets__
Dein Fehler liegt darin zu glauben, das einfach nur einen Namen im SQL zu benutzen, der auch außerhalb bekannt ist, dazu führt, das dann daraus eine Variable wird. Das ist so nicht, und wäre auch fatal, wenn es so wäre.
In den Posts vorher in diesem Thread den du gemopst hast wird aber auch genau das schon erklärt. Bitte lesen.
Re: variable per UPDATE einfügen
Verfasst: Montag 24. Juli 2017, 08:27
von nobby46
@ __deets__
danke für Deine Antwort, leider komme ich trotz mehrfachen lesen des Thread nicht weiter.
Ich habe versucht Deinen Tipp "cursor.execute("UPDATE Tabelle WHERE spalte = ?", (wert, ))"
bei mir zu übertragen, bekomme aber dann Fehlermeldung: near "WHERE": syntax error.
Mein angepasster UPDATE-Eintrag:
Code: Alles auswählen
cursor.execute("UPDATE temperaturen WHERE fuehler = ?", (Aussenf, )
Meine Tabelle habe ich so erstellt
Code: Alles auswählen
sql = """
CREATE TABLE temperaturen (
id INTEGER PRIMARY KEY,
name TEXT,
fuehler REAL
)"""
Was mache ich falsch?
Norbert
Re: variable per UPDATE einfügen
Verfasst: Montag 24. Juli 2017, 09:00
von __deets__
Das ist kein gültiges SQL. Und sieht anders aus als das, was du vorher gepostet hast. Warum?
Re: variable per UPDATE einfügen
Verfasst: Montag 24. Juli 2017, 10:52
von __deets__
Nachtrag: es war schon urspruenglich mein Fehler, das SQL hat nicht gestimmt. Aber es ging auch darum die Uebergabe der Parameter zu illustrieren. Ich habe das ja nicht selbst laufen gelassen.
Sirius hat meinen Fehler dann auch korrigiert, es steht als - nach wie vor - alles hier. Und du wirst auch nicht besonders weit kommen, wenn du ohne nachzudenken einfach Dinge kopierst. Du musst die Muster und Vorgehensweisen schon auf das adaptieren, was *du* tust.
Re: variable per UPDATE einfügen
Verfasst: Montag 24. Juli 2017, 11:04
von nobby46
@__deets__
mein erster Eintrag
Code: Alles auswählen
test = 2
sql = """
UPDATE temperaturen SET fuehler = test WHERE id = 1
"""
conn.execute(sql)
sollte zeigen wie es funktioniert wenn ich anstelle test eine Zahl z.B 25.3 eintrage.
Bei Eintragung test bekomme ich Fehlermeldung: sqlite3.OperationalError: no such column: test
Auf Anraten von Dir habe ich dann Deinen Vorschlag
Code: Alles auswählen
cursor.execute("UPDATE Tabelle WHERE spalte = ?", (wert, ))
bei mir so
Code: Alles auswählen
cursor.execute("UPDATE temperaturen WHERE fuehler = ?", (Aussenf, )
umgesetzt mit Fehlermeldung OperationalError: near "WHERE": syntax error
Um zu zeigen wie meine Tabelle aufgebaut ist,
Code: Alles auswählen
sql = """
CREATE TABLE temperaturen (
id INTEGER PRIMARY KEY,
name TEXT,
fuehler REAL
)"""
habe ich diese mit angehängt
Norbert
Re: variable per UPDATE einfügen
Verfasst: Montag 24. Juli 2017, 11:15
von nobby46
@--deets--
wo wir schon dabei sind, von mir auch ein Nachtrag. Deiner ist gekommen während ich geschrieben habe
Ich habe mich erst seit ein paar Tagen mit SQL beschäftigt und muss noch viel lernen. Deshalb habe ich noch nicht verstanden, wie ich den Eintrag von sirius3 bei mir umsetzen kann.
Werde weiter lernen
Norbert
Re: variable per UPDATE einfügen
Verfasst: Montag 24. Juli 2017, 12:04
von Sirius3
@nobby46: Vergleiche
[codebox=sql file=Unbenannt.sql]UPDATE temperaturen SET fuehler = test WHERE id = 1[/code]
mit
[codebox=sql file=Unbenannt.sql]UPDATE temperaturen WHERE fuehler = ?[/code]
und nenne 7 Unterschiede.
Re: variable per UPDATE einfügen
Verfasst: Montag 24. Juli 2017, 12:27
von nobby46
@Irius3
danke für Deinen heißen Tipp. Ich hatte mir gerade schon Deinen Eintrag
cursor.execute("UPDATE tabname SET aktwert = ?, turn = ? WHERE spalte = ?", ('1', zeit, 17))
angesehen und auf meine Bedürfnisse angepasst.
Code: Alles auswählen
cursor = conn.cursor()
cursor.execute("UPDATE temperaturen SET fuehler = ? WHERE id = 1", (Aussenf, ))
cursor.execute("UPDATE temperaturen SET fuehler = ? WHERE id = 2", (Innenf, ))
conn.commit()
und alles funktioniert wie es. Hat mir sehr geholfen. Ich muss aber noch viel lernen was Datenbanken und SQL unter Python angeht. Vor vielen Jahren als ich noch Berufstätig war habe ich viel in Assembler und C programmiert, aber lang ist's her
Nochmal danke.
Norbert
Re: variable per UPDATE einfügen
Verfasst: Montag 24. Juli 2017, 15:54
von BlackJack
@nobby46: Welches PHP-Programm speichert denn Zeitangaben nicht als DATETIME oder TIMESTAMP, sondern als TEXT/CHAR/VARCHAR in so einem komischen Format? Datenbanken haben doch extra Datentypen für so etwas. Zum Beispiel um Messdaten in einem bestimmten Zeitraum abzufragen. Das funktioniert mit Zeiten als Zeichenketten entweder nicht richtig oder mindestens ineffizienter.
Tabellennamen würde ich in Einzahl benennen. Denn so ein CREATE beschreibt *einen* Datensatz, also woraus *eine* Temperatur besteht. Das ist äquivalent zu einer Klassendefinition, oder in C eine Struktur. Hier würde `temperaturen` für die Struktur ja auch irreführend sein:
[codebox=c file=Unbenannt.c]typedef struct {
int id;
char *name;
double wert;
} temperatur;[/code]
Ich habe da `wert` statt `fuehler` als Bezeichnung für die Temperatur genommen, denn ``temperatur.wert = 42.23;`` macht mehr Sinn als ``temperatur.fuehler = 42.23;``. Das ist bei SQL nicht anders.
Zur Namenschreibweise in Python gibt's den
Style Guide for Python Code. Ausser Konstanten (ALLES_GROSS) und Klassen (MixedCase) schreibt man Namen klein_mit_unterstrichen. Also `aussenf` statt `Aussenf`. Wobei mir das `f` hier unklar ist (Fahrenheit? Bitte, bitte nicht `float`!), und `aussen` etwas zu unpräzise. `aussentemperatur` wäre passend wenn es die Aussentemperatur ist.
`connection` würde ich auch nicht abkürzen. Oder wenn dann vielleicht als `db` schreiben, denn das ist wenigstens eine gängige Abkürzung.
Und ich plädiere immer wieder gerne dafür SQLAlchemy als Abstraktionsschicht zu verwenden. Mindestens den Teil der vermeidet das man SQL von Hand schreiben muss, aber auch gerne das ORM.
Ohne ORM (ungetestet):
Code: Alles auswählen
for id_, temperatur in [(1, aussentemperatur), (2, innentemperatur)]:
connection.execute(
temperature_table.update()
.where(temperature_table.c.id=id_)
.values(wert=temperatur)
)
connection.commit()
Mit ORM (ungetestet):
Code: Alles auswählen
for id_, temperaturwert in [(1, aussentemperatur), (2, innentemperatur)]:
(
session.query(Temperatur)
.filter_by(id=id_)
.update({Temperatur.wert: temperaturwert})
)
session.commit()