SQLite INSERT - ON DUPLICATE KEY UPDATE (UPSERT)


98

MySQL ha qualcosa del genere:

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

Per quanto ne so questa funzionalità non esiste in SQLite, quello che voglio sapere è se esiste un modo per ottenere lo stesso effetto senza dover eseguire due query. Inoltre, se questo non è possibile, cosa preferisci:

  1. SELEZIONA + (INSERT o UPDATE) o
  2. UPDATE (+ INSERT se UPDATE fallisce )

Risposte:



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

Ciò richiede che la colonna "ip" abbia un vincolo UNIQUE (o PRIMARY KEY).


EDIT: un'altra ottima soluzione: https://stackoverflow.com/a/4330694/89771 .


2
Solo per la cronaca, REPLACEnon è un'opzione.
Alix Axel

1
Per quanto riguarda il "un'altra grande soluzione", inserite Vorrei anche prendere in considerazione una risposta diversa alla stessa domanda: stackoverflow.com/a/418988/3650835
KayakinKoder

19

Preferirei UPDATE (+ INSERT if UPDATE fails). Meno codice = meno bug.


1
Grazie! @ Sam ( stackoverflow.com/questions/418898/... ) sembra essere d'accordo con te. Anch'io preferisco questo approccio.
Alix Axel

@ Smith Intendevo usare semplici istruzioni UPDATE e INSERT e controllare il valore di ritorno.
codeholic

Questo non ha atomicità, è possibile che INSERT fallisca se qualche altro processo viene inserito nel mezzo.
Robin Lavallée

7

La risposta corrente funzionerà solo in sqlite OR mysql (a seconda che tu usi OR o meno). Quindi, se vuoi la compatibilità cross dbms, quanto segue farà ...

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

3
La risposta accettata funziona su SQLite (questo era il mio obiettivo). REPLACEfunzionerà anche su SQLite, ma su MySQL reimposterà sempre il contatore a 0 - mentre la query sarà portabile, il risultato finale sarà molto diverso.
Alix Axel

Hai ragione, pensavo che l'OP stesse cercando qualcosa che fosse portatile. Mi rendo conto che REPLACE INTO non funzionerà con tutti i casi, specialmente dove è necessaria la conservazione PK, ma lo farà per molti casi.
Jacob Thomason

Fallire in modo pulito invece di scartare i dati è una caratteristica, non un bug.
Tobu

-4

Dovresti usare memcached per questo poiché è una singola chiave (l'indirizzo IP) che memorizza un singolo valore (il numero di visite). È possibile utilizzare la funzione di incremento atomico per assicurarsi che non vi siano condizioni di "gara".

È più veloce di MySQL e salva il carico in modo che MySQL possa concentrarsi su altre cose.


Se i dati non sono così importanti, sì. Tuttavia, se questo viene utilizzato su un sito occupato in cui molti IP stanno raggiungendo il servizio, le istanze memcached potrebbero riempirsi e causare la caduta di alcuni contenuti. Anche il backup dei contenuti memorizzati nella cache sarebbe interessante (se necessario)
Elliot Foster

@ElliotFoster Memcached può gestire tanti dati quanto la RAM che gli lanci (se vuoi persitenza, usa anche redis o membase). Se ricevi oltre 1 milione di visitatori al giorno, probabilmente puoi permetterti di dare alla tua istanza di memcache più di 30 MB di ram (che è l'impostazione predefinita, credo). Tuttavia, può certamente gestire un carico molto più elevato di SQLite e MySQL per la quantità di memoria che gli dai - semplicemente non c'è confronto.
Xeoncross

Per favore, non confondere il mio commento con un voto contro memcache, poiché penso che sia uno strumento fantastico. Come è redis (non posso parlare per membase, poiché non l'ho usato.) Tuttavia, memcache / redis non sono i negozi più affidabili. Sì, redis ha persistenza, ma i dati vengono conservati su disco su un intervallo (l'ultima volta che ho guardato) e memcache per niente. Come ho detto, se i dati non sono importanti (o possono essere riprodotti facilmente), memcache e company sono fantastici. Il post originale chiedeva anche di sqlite, che è molto diverso da MySQL e probabilmente significa che sono limitati in altri modi.
Elliot Foster

È possibile configurare Redis per rendere persistenti i dati alla velocità desiderata (al numero X di secondi o al numero Y di modifiche).
Buffalo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.