2016-04-17 4 views
0

Ich bin mit SQLite speichern einen id, Uuid, Wert und ein gefangen Wert.SQLite 'INSERT INTO OR REPLACE' falsches Verhalten

I Erstellen Sie die Tabelle mit diesem Befehl:

CREATE TABLE IF NOT EXISTS statz_fish_caught 
('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
'uuid' TEXT NOT NULL, 
'value' INTEGER NOT NULL, 
'caught' TEXT NOT NULL); 

ich diesen Befehl verwenden, um ein (oder ersetzen) Zeilen:

INSERT OR REPLACE INTO statz_fish_caught (uuid,value,caught) 
VALUES ('uuid comes here', a number here, 'a certain string'). 

Angenommen, Sie haben diese Daten in der Tabelle haben:

http://pasteboard.co/gofap3y.png

Diese Daten würden bedeuten, dass UUID1 abgefangen wurde insgesamt 9 (1 + 5 + 3) Fische. 1 von Fisch Typ 1, 5 von Fisch Typ 2 und 3 von Fisch Typ 3. UUID2 hat nur 10 Fische vom Fisch Typ 1 gefangen. Nun stellen wir uns vor, UUID1 fängt einen neuen Fisch Typ: Fisch Typ 4. Die Datenbank sollte eine neue Zeile erstellen mit einem auto erhöhte Wert von id 5, mit Uuid als ‚uuid1‘, Wert = 1 und = Fischart 4.

Nun wollen wir auch UUID vorstellen gefangen fängt einen anderen Fisch Fisch Typ 3. Die Reihe von uuid1 mit Fischart 3 (es hat ID 3) soll Wert 4, so repräsentieren aktualisiert werden:

http://pasteboard.co/goBZatx.png

Ist das möglich, wenn ja, wie?

Antwort

1

Sie verwenden eine , und Sie haben keine anderen UNIQUE Feld in Ihrer Tabelle: Das bedeutet, dass es keinen Konflikt zwischen den vorhandenen Zeilen und der, die Sie hinzufügen möchten, gibt es daher sein nicht REPLACE

Sie sollten die Definition Ihrer Tabelle wie folgt ändern:

CREATE TABLE IF NOT EXISTS statz_fish_caught 
('id' INTEGER PRIMARY KEY NOT NULL, 
'uuid' TEXT NOT NULL, 
'value' INTEGER NOT NULL, 
'caught' TEXT NOT NULL); 

Bitte beachten Sie, dass durch diese Änderung müssen Sie manuell den id Wert setzen, wenn Sie die Zeilen hinzufügen, da es nicht ist vom DBMS verwaltet.

Bearbeiten: Here Sie können ein funktionierendes Beispiel finden; Beachten Sie, wie sich der Wert des Primärschlüssels nicht geändert hat.

Edit # 2: Wie ishmaelMakitla vorgeschlagen, UNIQUE für das UUID Feld setzen sollte es tun; Ich habe meine Antwort entsprechend aktualisiert.

CREATE TABLE IF NOT EXISTS statz_fish_caught 
('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
'uuid' TEXT NOT NULL UNIQUE, 
'value' INTEGER NOT NULL, 
'caught' TEXT NOT NULL); 

Eine Warnung: wie in der SQLite-Dokumentation angegeben,

Das Schlüsselwort AUTOINCREMENT erlegt zusätzliche CPU, Arbeitsspeicher, Festplattenspeicher und Festplatten-E/A-Aufwand und sollte nicht unbedingt erforderlich vermieden werden. Es wird normalerweise nicht benötigt.

Plus, wie Sie in this Beispiel sehen, die id der aktualisierten Zeile geändert hat, was etwas ist, das ich zu vermeiden, empfehlen stark.

Edit # 3 Ich brauchte eine Weile, aber this Beispiel sollte das tun, was Sie wollen.

Die Abfrage, die Sie verwenden müssen, ist so etwas wie dieses (6 die gefangenen Fische Sie hinzufügen möchten, ist):

INSERT OR REPLACE INTO statz_fish_caught (uuid,value,caught) 
VALUES (
    -- (select `id` from statz_fish_caught where uuid = 'uu1'), 
    'uu1', 
    (select `value` from statz_fish_caught where uuid = 'uu1') + 6, 
    (select `caught` from statz_fish_caught where uuid = 'uu1') 
); 

Beachten Sie, dass, wenn Sie für die Aktualisierung des aktuellen Wertes des id Feld halten Zeile, müssen Sie die erste Zeile der Werte auskommentieren und das Feld id in der Liste der Spalten der Anweisung hinzufügen.

+0

Dies ist in der Tat, was ich brauche gibt es eine Möglichkeit, die DBMS automatisch die id-Spalte tut Wenn nicht, wie würde ich mich über manuell zu gehen.? Aktualisierung der ID jedes Mal ? Ich müsste zuerst wissen, was die ID ist, oder? – Staartvin

+0

Um das Autoinkrement loszuwerden, sollten Sie sich mit dem Benutzer dieser Datenbank erkundigen, wenn ein anderes Feld als Primärschlüssel verwendet werden kann. Wenn Sie aus irgendeinem Grund mit dem Autoinkrement stecken bleiben (was theoretisch nicht der beste Ansatz ist), können Sie ein anderes Feld als "EINZIGARTIG" festlegen, wie in der anderen Antwort vorgeschlagen. Auf diese Weise wird das Ersetzen wirksam, wenn dieses Feld einen Konflikt hat. – Cynical

+0

Es scheint, ich bin zu vage. Ich habe meinen ursprünglichen Post mit verschiedenen Bildern aktualisiert, die erklären, was jede Spalte bedeutet. Gibt es eine Möglichkeit, mit SQLite zu arbeiten? (Btw, du bist zweite Lösung war nicht das, was ich gesucht habe, tut mir leid!) – Staartvin

0

Zusätzlich zu dem, was Cynical sagte, sollten Sie UUID auf UNIQUE setzen - auf diese Weise wird die Zeile mit einer passenden UUID ersetzt. So sollte die Tabelle wie folgt geändert werden:

CREATE TABLE `statz_fish_caught` (
`id` INTEGER NOT NULL, 
`uuid` TEXT NOT NULL UNIQUE, 
`value` INTEGER NOT NULL, 
`caught` TEXT NOT NULL, 
PRIMARY KEY(id) 
); 

ich diese getestet haben, indem Sie die folgenden Schritte aus:

INSERT OR REPLACE INTO statz_fish_caught 
(uuid,value,caught) VALUES (hex(randomblob(16)), 1, 'caught-1 '); 

Dann ausgeführt ich die folgende Abfrage-String (beachten Sie, benutzte ich die UUID von Hex erzeugt (randomblob (16) in der vorherige Abfrage) Also, indem Sie:.

INSERT OR REPLACE INTO statz_fish_caught (uuid,value,caught) VALUES ('uuid-of-row-to-update', 2, 'caught-1-updated'); 
+0

Ich denke, ich war nicht klar genug. Die Spalte _caught_ kann mehrere Werte haben, sollte aber gruppiert werden, wenn sie identisch ist. Es sollte funktionieren wie [dies] (http://sqlfiddle.com/#!5/eecd2/1), aber ** mit ** der automatischen Behandlung der _id_ Spalte. Ist das möglich. – Staartvin

+0

In meiner Antwort ging ich davon aus, dass die UUID für einen Ersatz identisch sein wird. Nun mit Ihrer Klarstellung, dann muss die "gefangen" -Spalte die UNIQUE-Einschränkung haben - andernfalls gibt es keine Möglichkeit zu wissen, welche Zeile die Abfrage ersetzen sollte. Als Ergebnis wird eine neue Zeile eingefügt. Der Grund, warum es funktioniert, wenn Sie den gleichen ID-Wert (1) in der Geige angeben, ist, weil die ID die eindeutige Einschränkung automatisch als Primärschlüssel hat. Dementsprechend sollten Sie Ihre Tabelle modifizieren, indem Sie die "gefangen" -Spalte eindeutig machen: 'erwischt TEXT NOT NULL UNIQUE,' – ishmaelMakitla

+0

Dies hat den Trick nicht gemacht. Sehen Sie meinen ursprünglichen Beitrag, ich habe ihn bearbeitet und klargestellt, was ich speziell von meiner Datenbank möchte. – Staartvin