SQLite INSERT - ON DUPLICATE KEY UPDATE (UPSERT)


98

MySQL hat ungefähr so ​​etwas:

INSERT INTO visits (ip, hits)
VALUES ('127.0.0.1', 1)
ON DUPLICATE KEY UPDATE hits = hits + 1;

Soweit ich weiß, ist diese Funktion in SQLite nicht vorhanden. Ich möchte wissen, ob es eine Möglichkeit gibt, denselben Effekt zu erzielen, ohne zwei Abfragen ausführen zu müssen. Wenn dies nicht möglich ist, was bevorzugen Sie:

  1. SELECT + (INSERT oder UPDATE) oder
  2. UPDATE (+ INSERT, wenn UPDATE fehlschlägt )

Antworten:



117
INSERT OR IGNORE INTO visits VALUES ($ip, 0);
UPDATE visits SET hits = hits + 1 WHERE ip LIKE $ip;

Dies erfordert, dass die Spalte "ip" eine EINZIGARTIGE (oder PRIMARY KEY) Einschränkung aufweist.


BEARBEITEN: Eine weitere großartige Lösung: https://stackoverflow.com/a/4330694/89771 .


2
Nur für die Aufzeichnung REPLACEist keine Option.
Alix Axel

1
In Bezug auf den Link "Eine weitere großartige Lösung" würde ich auch eine andere Antwort auf dieselbe Frage in Betracht
ziehen

19

Ich würde es vorziehen UPDATE (+ INSERT if UPDATE fails). Weniger Code = weniger Fehler.


1
Vielen Dank! @Sam ( stackoverflow.com/questions/418898/… ) scheint Ihnen zuzustimmen. Ich bevorzuge auch diesen Ansatz.
Alix Axel

@Smith Ich meinte, einfache UPDATE- und INSERT-Anweisungen zu verwenden und den Rückgabewert zu überprüfen.
Codeholic

Dies hat keine Atomizität. Es ist möglich, dass INSERT fehlschlägt, wenn ein anderer Prozess dazwischen eingefügt wird.
Robin Lavallée

7

Die aktuelle Antwort funktioniert nur in SQLite ODER MySQL (je nachdem, ob Sie OR verwenden oder nicht). Wenn Sie also Cross-DBMS-Kompatibilität wünschen, reicht Folgendes aus ...

REPLACE INTO `visits` (ip, value) VALUES ($ip, 0);

3
Die akzeptierte Antwort funktioniert unter SQLite (das war mein Ziel). REPLACEfunktioniert auch unter SQLite, aber unter MySQL wird der Zähler immer auf 0 zurückgesetzt - während die Abfrage portierbar ist, unterscheidet sich das Endergebnis stark.
Alix Axel

Sie haben Recht, ich dachte, das OP sucht nach etwas, das tragbar ist. Mir ist klar, dass REPLACE INTO nicht in allen Fällen funktioniert, insbesondere wenn eine PK-Aufbewahrung erforderlich ist, aber in vielen Fällen.
Jacob Thomason

Ein fehlerfreier Fehler, anstatt Daten zu verwerfen, ist eine Funktion, kein Fehler.
Tobu

-4

Sie sollten hierfür memcached verwenden, da es sich um einen einzelnen Schlüssel (die IP-Adresse) handelt, in dem ein einzelner Wert (die Anzahl der Besuche) gespeichert ist. Sie können die atomare Inkrementfunktion verwenden, um sicherzustellen, dass keine "Race" -Bedingungen vorliegen.

Es ist schneller als MySQL und spart die Last, sodass sich MySQL auf andere Dinge konzentrieren kann.


Wenn die Daten nicht so wichtig sind, ja. Wenn dies jedoch auf einer ausgelasteten Site verwendet wird, auf der viele IP-Adressen den Dienst erreichen, werden die zwischengespeicherten Instanzen möglicherweise voll und führen dazu, dass Inhalte gelöscht werden. Das Sichern von zwischengespeicherten Inhalten wäre ebenfalls interessant (falls erforderlich)
Elliot Foster,

@ElliotFoster Memcached kann so viele Daten verarbeiten wie der RAM, den Sie darauf werfen (wenn Sie auch Ausdauer wünschen, verwenden Sie redis oder membase). Wenn Sie mehr als 1 Million Besucher pro Tag haben, können Sie es sich wahrscheinlich leisten, Ihrer Memcache-Instanz mehr als 30 MB RAM zu geben (was meiner Meinung nach die Standardeinstellung ist). Es kann jedoch mit Sicherheit eine viel höhere Last als SQLite und MySQL für die Menge an Speicher bewältigen, die Sie ihm geben - es gibt einfach keinen Vergleich.
Xeoncross

Bitte verwechseln Sie meinen Kommentar nicht als Abstimmung gegen Memcache, da ich denke, dass dies ein fantastisches Werkzeug ist. Wie Redis (Ich kann nicht für Membase sprechen, da ich es nicht verwendet habe.) Memcache / Redis sind jedoch nicht die zuverlässigsten Speicher. Ja, Redis hat eine Persistenz, aber die Daten bleiben in einem Intervall (zuletzt habe ich nachgesehen) auf der Festplatte erhalten und der Memcache überhaupt nicht. Wie gesagt, wenn die Daten nicht wichtig sind (oder leicht reproduziert werden können), sind Memcache und Firma großartig. Der ursprüngliche Beitrag fragte auch nach SQLite, das sich stark von MySQL unterscheidet und wahrscheinlich bedeutet, dass sie auf andere Weise eingeschränkt sind.
Elliot Foster

Sie können Redis so konfigurieren, dass Daten so schnell wie gewünscht gespeichert werden (bei X Sekunden oder bei Y Anzahl von Änderungen).
Buffalo
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.