Update einer Spalte / alle Zeilen

Stefke

Benutzer
Beiträge
17
Hallo, ich versuche grad alle Zeilen einer Spalte zu aktualisieren:
Code:
SELECT diff_sec from feeds;
UPDATE feeds SET diff_sec = (300, 303, 303, 303, 303, ...... 303);
hier nur ein Auszug der Liste, die Länge der Liste und die Anzahl der Zeilen sind identisch
erzeugt den Fehler:
Code:
[ERROR] row value misused
Wo kann das Problem liegen?
Code:
UPDATE feeds SET diff_sec = 300;
wird fehlerfrei ausgeführt.

Danke - Stefan
 
Werbung:
Ich könnte mir bei dem falschen Statement und Deiner Frage/ Herangehensweise vorstellen, dass Dir grundlegende Konzepten der Datenverarbeitung mit SQL nicht klar sind.
Aber zunächst:
Wenn Du nicht verrätst, welchen Typ die Spalte hat, wird niemand eine gute Antwort gelingen.
(wobei auch hier wieder die sqlite Besonderheit mit der Typaffinität zum Tragen kommt)
Die Fehlermeldung gibt ja schon einen groben Eindruck: sqlite glaubt, du möchtest eine ganze Zeile (mehrere Spalten) in eine Spalte quetschen.
Da Du keine where Clause angegeben hast, würde es das in jeder existierenden Zeile machen. Weil aber schon gleich zu Anfang ein Fehler kommt, bricht das Statement bei der ersten Zeile ab.

Vorschlag:
Versuche zu Deinem Verständnis zunächst, genau eine bestimmte Zeile zu aktualisieten.
Wenn Du das geschafft hast, versuche 2 Zeilen zu aktualisieren.
 
UPDATE behandelt alle betroffenen Zeilen gleich. Das heißt, du versuchst der Spalte diff_sec in jedem Datensatz eine Art Werteliste mit zu geben, das ist so natürlich Quatsch.

Vermutlich willst du jeder Zelle einen Wert aus dieser Werteliste geben. Dazu müsste SQL aber zunächst einmal wissen, welche Zeile welchen Wert bekommen soll. Die Logik dahinter kennen wir aber nicht, daher ist es schwer, eine Empfehlung zu geben. ein Join oder ein CASE kann sinnvoll sein. Wenn der Wert von einer anderen Spalte abhängt, geht es auch mit einer Funktion. Dann ergibt aber die Existens der Spalte häufig keinen Sinn.
 
Die einzufügende Werte sind alle vom Typ 'Integer' und der Datenbankspalte 'diff_sec' ist gleichfalls der Typ 'Integer' zugeordnet.
Code:
UPDATE feeds SET diff_sec = 315 WHERE Rowid = 1, diff_sec = 316 WHERE Rowid = 2;
sollte sinngemäß funktionieren - tut es aber nicht.
SQlite ist irdendwie nicht meins ... leider.
 
Du brauchst etwas in der Art:

Code:
update feeds
    set diff_sec = case rowid
                     when 1 then 315
                     when 2 then 316
                     else diff_sec
                   end
where rowid in (1,2)

Hat aber nichts speziell mit SQLite zu tun, sondern mit SQL im Allgemeinen.
 
Zuletzt bearbeitet:
Ja die Syntax ist allgemein falsch. Mit Komma getrennte Werte kenne ich jetzt so erstmal nur von INSERT.

@castorp hat eine Variante mit CASE vorgeschlagen, die ist aber aus meiner Sicht nicht so gut wenn man für jeden einzelnen Datensatz ein CASE definieren muss. Du könntest deinen Statement
Code:
UPDATE feeds SET diff_sec = 315 WHERE Rowid = 1, diff_sec = 316 WHERE Rowid = 2;
sehr leicht fixen und einfach zerlegen:
Code:
UPDATE feeds SET diff_sec = 315 WHERE Rowid = 1;
UPDATE feeds SET diff_sec = 316 WHERE Rowid = 2;
Daneben gäbe es auch noch andere Varianten, aber wenn der Zielwert komplett individuell pro Datensatz ist und sich nicht aus anderen Spalten oder anderen Tabellen ermitteln läßt dann würde man wohl eher einzelne UPDATE-Statements an die DB schicken.
 
Danke, genauso habe ich die DB aktualieren können:
Code:
def main(): 
    query = "SELECT Datum from feeds"
    verbindung = sqlite3.connect("thingspeak_db.db")
    c = verbindung.cursor()
    c.execute(query) #Anweisung ausführen
    date_list = c.fetchall()
    for i in range(1,len(date_list)):
        start_time = (''.join(date_list[i-1]))
        end_time = (''.join(date_list[i]))
        qstart_time = QDateTime.fromString(start_time, 'yyyy-MM-dd hh:mm:ss')
        qend_time = QDateTime.fromString(end_time, 'yyyy-MM-dd hh:mm:ss')
        sec = qstart_time.secsTo(qend_time)
        query = f"UPDATE feeds SET diff_sec = {sec} WHERE Rowid = {i}"
        c.execute(query) #Anweisung ausführen
        verbindung.commit()
    c.close() # Cursor trennen
    verbindung.close() # Verbindung zur Datenbank trennen
    print("qery fertig")

if __name__ == '__main__':
    main()
aus Spalte 'Datum' das Datum entnehmen und die Differenz in Sekunden in die Spalte 'diff_sek' eintragen.

Danke :)
 
Normalerweise würde ich sagen, das kannst du einfacher haben. Kürzlich habe ich allerdings gelernt das SQLite etwas speziell ist, und z.B. keinen Datentypen für Datum und/oder Zeit hat. Eventuell gibt es aber wohl eine Möglichkeit, auf Datenbank-Ebene mit Zeitwerten zu arbeiten. Dann wäre das genau eine Zeile an die Datenbank, etwa
Code:
UPDATE feeds SET diff_sec = timediff(seconds,start_time,end_time) WHERE diff_sec IS NULL
Die Funktionen sind in SQLite vermutlich anders, als in anderen Datenbanken. Der Vorteil ist aber klar das du keine Schleife bauen musst (immer böse) und das die Daten auch gar nicht erst aus der DB geladen werden müssen. Du sagst der DB nur, setze den Wert auf Basis dieser zwei anderen Werte.
 
Wenn man einen Wert ohne großen Aufwand direkt aus anderen Spalten der Tabelle berechnen kann, würde ich den überhaupt nicht in einer eigenen Spalte speichern.

Wenn man die "Formel" nicht jedesmal wieder tippen will, kann man ja eine View definieren, die diese Berechnung ausführt.
 
aber das Script ist durchgelaufen, Datenbank ist fertig - sehr schön
Ich bin mir sicher, Du wirst irgendwann ein ähnliches Problem haben.

Also 2 Hinweise dazu:
1. Updates eines einzelnen Datensatzes beziehen sich fast immer auf den Primärschlüssel*
2. Eine Menge von Datensätzen zu aktualisieren und dazu ein Programm zu schreiben ist möglich, aber nicht effizient und nicht schnell, je größer die Anzahl der zu aktualisierenden Datensätze, desto mehr fällt das Problem auf

zu 1
jede Tabelle sollte diesen Primärschlüssel haben, damit ein Datensatz eindeutig identifizierbar ist. So kann jeder beliebige Datensatz mit spezifischen Werten aktualisiert werden.

zu 2
Ein Client Programm, das jeden Datensatz runterlädt, aktualisiert und wieder zu DB schickt, ist fürchterlich langsam. Fühlbar wird das vielleicht bei ein paar Tausend Datensätzen, irgendwann tut es weh, dauert ewig...
Um das zu vermeiden, nutzt man bspw. Programmcode auf dem Server (gibt es bei sqlite nicht, siehe Caravan Frage) oder Update Statements, die sich korrelierte Updates nennen. Letzteres erfolgt auf dem Server, ist unschlagbar schnell und lediglich ein einziges Statement ohne Programmcode.

* Es gibt viele Situationen besonders beim Anlegen, initialen Befüllen, Entwickeln einer DB, wo man exotische Statements ausführt, vielleicht wie Deins oben, die sozusagen außer der Reihe, einmalig benötigt werden, um irgendeinen Datenbestand "grade zu ziehen". Und da darf man ruhig den bequemsten Weg gehen. Für eine regelhafte Anwendung von Statements sollte man dann genauer überlegen, was man tut. Es sei denn, es ist ein reines Privatprojekt, man hat Zeit und tut damit niemand weh.
 
Werbung:
Ha, ich stimme Dir in allen Punkten gänzlich zu. Als 'Unwissender' ist es halt schwierig im Voraus den Rahmen des Scriptes zu erfassen und abzustecken. Als Folge davon ergeben sich dann öfters solche Probleme wie oben.

Aber es ist ne reine Privatbastelei:
in der Gartenlaube steht ein Raspi der Meßwerte im 5-min-Takt an Thingspeak sendet,
dann ruft das Pythonscript die Daten auf den heimischen Rechner und gestaltet sie zum Diagramm (PySide6).

früher hab ich das mit MS-Office umgesetzt, dann den Code in Python für LibreOffice geschrieben. Aber Office und LO kommen mit derzeit 160000 Datensätze nicht wirklich zurecht.🐌

Daher hatte ich mich mit PyQt befasst und und die graphische Oberfläche selbst zusammen gestellt.
Der Geschwindigkeitsunterschied zu Office und LO ist bei derzeit 160000 Datensätzen schon berauschend schnell.

Aus dieser Situation heraus ist es sehr schön, dass es hier so hilfsbereite Helfer gibt. Bitte nicht verzweifeln bei Fragen die den Wissensstand des Threaderstellers verraten.....:):(

Danke - Stefan
 
Zurück
Oben