NEWS
SQL sendTo - Problem storeState vs update
-
Ich nutze
sendTo
um historische Werte in die Datenbank zu schreiben:sendTo("sql.0", "storeState", { "id": myId, "state": { "val": myVAL, "ts": myTS, "ack": true } }, async function (result) { //console.log(result); });
Bisher habe ich immer, bevor ich das gemacht habe, vorher alle Datenpunkte gelöscht:
// Alles löschen sendTo("sql.0", "deleteAll", { "id": myIdDeleteAll, }, async function (result) { //console.log(result); });
Nun würde ich dei Werte aber gerne fortschreiben, dabei kann es sein das alles Werte schon vorhanden sind, kann auch sein das neue hinzukommen. Wenn ich nun weiter
storeState
nehme bekomme ich Fehlermeldungen:2022-06-06 12:45:08.881 - error: sql.0 (1910630) Cannot insert INSERT INTO `iobroker`.ts_number (id, ts, val, ack, _from, q) VALUES (104, 1654631220000, 0, 1, 0, 0);: Error: Duplicate entry '104-1654631220000' for key 'PRIMARY' (id: 0_userdata.0.Solaranlage.pvforecasts.Forecast_solar.600W)
Ok, dafür müsste ich
update
nehmen:sendTo("sql.0", "update", { "id": myId, "state": { "val": myVAL, "ts": myTS, "ack": true } }, async function (result) { //console.log(result); });
update
funktioniert aber nur wenn es den den Eintrag schon gibt. Wenn es den nicht gibt verschwindet der Wert im Nirwana.
Ich habe in der Hilfe und im Forum nichts gefunden (oder verwende die falschen Suchbegriffe):Gibt es eine Möglichkeit aka "Erstelle wenn noch nicht vorhanden, ansonsten aktualisiere"?
Oder müsste ich für jeden Wert vorher prüfen ob es diesen gibt und dann die entsprechende Methode nehmen? -
@bananajoe du könntest sendTo("sql.0", "query", sql_statement.....) verwenden und da dein eigenes SQL verwenden. Für MariaDB gibt es das REPLACE INTO TABLE statement oder auch das INSERT ON DUPLICATE KEY UPDATE statement.
Wenn das gut funktioniert könnte man auch überlegen ob man storeState evtl. damit ersetzen kann, sprich ein enhancement issue erstellt
-
@fastfoot Dann müsste ich mich selbst darum kümmern erst die Zuordnung den Tabellen
datapoints
undts_numbers
zu holen ... mhh, steht ja auch in einem der Beispiele zum Adapter.Ich habe mich gerade an einer Prüfung versucht ob es den Wert denn schon gibt.
getHistory
will mir eigentlich einen Zeitbereich zurück geben, ich will aber ja genau einen Wert dessen Zeitstempel ich kenne .. und scheitere gerade auch daran (bekomme immer leer Abfrage zurück).Da hab ich noch einen Moment zu tun ...
-
@bananajoe nichts ist unmöglich
REPLACE INTO ts_number (id,ts,val,ack,_from,q) VALUES ((SELECT id FROM datapoints WHERE NAME = "tankerkoenig.0.stations.5.e5.feed"), 1654516496102, 1.029, 1, 1, 0)
funktioniert -
@bananajoe sagte in SQL sendTo - Problem storeState vs update:
Ich habe mich gerade an einer Prüfung versucht ob es den Wert denn schon gibt.
hier mal ein fertiges Beispiel, wozu prüfen wenn die DB das auch kann?
let id = 'tankerkoenig.0.stations.5.e5.feed'; let ts = 1654516496145; let value = 0.029; let ack=1; let _from=1; let q=0; let statement = ` REPLACE INTO iobroker.ts_number (id, ts, val, ack, _from, q) VALUES ((SELECT id FROM iobroker.datapoints WHERE name = "${id}"), ${ts}, ${value}, ${ack}, ${_from}, ${q}) ` //log(statement) sendTo("sql.0", "query", statement, e => { if (e && e.error) log(e.error) else log("Done!") })
-
@fastfoot mhh, dein Beispiel versucht den Wert zu aktualisieren, wenn das klappt kommt der
else log("Done!")
Zweig, ansonsten derif (e && e.error) log(e.error)
?Wenn es einen Fehler gibt müsste ich dann also noch mal mit
storeState
nachsetzen?Mein Problem ist vermutlich auch eher der Natur das ich das in Blockly in einer JS Funktion nutzen möchte und - wieder einmal - Probleme hatte die Variablen so ins Statement einzubauen das er es ohne meckern annimmt.
Dein Weg wäre natürlich viel eleganter, schon mal Danke für die Mühe.
-
@bananajoe sagte in SQL sendTo - Problem storeState vs update:
Wenn es einen Fehler gibt müsste ich dann also noch mal mit storeState nachsetzen?
nein! wenn es die id zB nicht gäbe dann wird dieser Fehler geloggt. Ansonsten kümmert sich das REPLACE INTO um doppelte Werte, d.h. wenn der Wert existiert (der primary key oder unique key) dann wird zuerst gelöscht und dann erfolgt das Insert, wenn nichts existiert erfolgt ein normales Update.
Probier doch einfach mal
-
@bananajoe hier als Blockly
-
@fastfoot Funktioniert 1A! Kein gemecker mehr im Log und in
mysql
sehe ich wie die Werte aktualisiert werden.Ich will nämlich neben Forecast.solar auch Solcast abfragen - die senden aber immer nur eine Vorhersage ab dem Zeitpunkt der Frage. Sieht in der Tagesgrafik von 0:00 bis 23:59 Uhr aber dann natürlich schlecht aus.
Abgesehen das ich auch so bisher in den Diagrammen nicht zurückgehen konnte bzw. dann halt die Vorhersage fehlte.
Besten Dank, ich vermute das kann ich noch an vielen anderen Stellen brauchen.
-