SQLite INSERT - NA DUPLICATE KEY UPDATE (UPSERT)


98

MySQL ma coś takiego:

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

O ile wiem, ta funkcja nie istnieje w SQLite, chciałbym wiedzieć, czy istnieje sposób na osiągnięcie tego samego efektu bez konieczności wykonywania dwóch zapytań. Jeśli nie jest to możliwe, co wolisz:

  1. SELECT + (INSERT lub UPDATE) lub
  2. UPDATE (+ INSERT, jeśli UPDATE nie powiedzie się )

Odpowiedzi:



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

Wymaga to, aby kolumna „ip” miała ograniczenie UNIQUE (lub PRIMARY KEY).


EDYCJA: Kolejne świetne rozwiązanie: https://stackoverflow.com/a/4330694/89771 .


2
Tak dla porządku, REPLACEnie ma takiej opcji.
Alix Axel,

1
Jeśli chodzi o link „kolejne świetne rozwiązanie”, rozważałbym również inną odpowiedź na to samo pytanie: stackoverflow.com/a/418988/3650835
KayakinKoder

19

Wolałbym UPDATE (+ INSERT if UPDATE fails). Mniej kodu = mniej błędów.


1
Dzięki! @Sam ( stackoverflow.com/questions/418898/… ) wydaje się zgadzać z tobą. Ja też wolę to podejście.
Alix Axel

@Smith Miałem na myśli używanie zwykłych instrukcji UPDATE i INSERT oraz sprawdzanie wartości zwracanej.
codeholic

To nie ma atomowości, możliwe, że INSERT nie powiedzie się, jeśli jakiś inny proces zostanie wstawiony pomiędzy.
Robin Lavallée

7

Bieżąca odpowiedź będzie działać tylko w sqlite LUB mysql (w zależności od tego, czy użyjesz OR, czy nie). Tak więc, jeśli chcesz kompatybilności z różnymi dbms, wykonaj następujące czynności ...

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

3
Zaakceptowana odpowiedź działa na SQLite (taki był mój cel). REPLACEbędzie działać również na SQLite, ale w MySQL zawsze zresetuje licznik do 0 - podczas gdy zapytanie będzie przenośne, wynik końcowy będzie się znacznie różnić.
Alix Axel,

Masz rację, myślałem, że OP szuka czegoś przenośnego. Zdaję sobie sprawę, że REPLACE INTO nie zadziała we wszystkich przypadkach, szczególnie tam, gdzie konserwacja PK jest potrzebna, ale w wielu przypadkach będzie.
Jacob Thomason,

Czyste niepowodzenie zamiast odrzucania danych jest funkcją, a nie błędem.
Tobu

-4

Powinieneś do tego użyć memcached, ponieważ jest to pojedynczy klucz (adres IP) przechowujący pojedynczą wartość (liczbę odwiedzin). Możesz użyć atomowej funkcji przyrostu, aby upewnić się, że nie ma warunków „wyścigu”.

Jest szybszy niż MySQL i oszczędza obciążenie, więc MySQL może skupić się na innych rzeczach.


Jeśli dane nie są takie ważne, tak. Jeśli jednak jest to używane w ruchliwej witrynie, w której wiele adresów IP trafia do usługi, instancja memcached może się zapełnić i spowodować upuszczenie części zawartości. Tworzenie kopii zapasowych zawartości pamięci podręcznej również byłoby interesujące (w razie potrzeby).
Elliot Foster,

@ElliotFoster Memcached może obsłużyć tyle danych, ile wrzucisz do niego pamięć RAM (jeśli chcesz zachować trwałość, użyj także redis lub membase). Jeśli masz ponad 1 milion odwiedzających dziennie, prawdopodobnie możesz pozwolić sobie na przekazanie swojej instancji memcache więcej niż 30 MB pamięci RAM (myślę, że jest to ustawienie domyślne). Jednak z pewnością może obsłużyć znacznie większe obciążenie niż SQLite i MySQL, biorąc pod uwagę ilość pamięci, którą mu dajesz - po prostu nie ma porównania.
Xeoncross

Nie mylcie mojego komentarza jako głosowania przeciwko memcache, ponieważ uważam, że to fantastyczne narzędzie. Podobnie jak redis (nie mogę mówić o membase, ponieważ jej nie używałem). Jednak memcache / redis nie są najbardziej niezawodnymi sklepami. Tak, redis ma trwałość, ale dane są utrwalane na dysku w odstępach czasu (ostatnio sprawdzałem), a memcache wcale. Jak powiedziałem, jeśli dane nie są ważne (lub można je łatwo odtworzyć), to memcache i firma są świetne. W oryginalnym poście pytano również o sqlite, który bardzo różni się od MySQL i prawdopodobnie oznacza, że ​​są one ograniczone w inny sposób.
Elliot Foster

Możesz skonfigurować Redis, aby utrwalał dane tak szybko, jak chcesz (przy X sekund lub przy Y liczbie zmian).
Buffalo,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.