INSERTAR SQLite - EN ACTUALIZACIÓN DE CLAVE DUPLICADA (UPSERT)


98

MySQL tiene algo como esto:

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

Por lo que sé, esta característica no existe en SQLite, lo que quiero saber es si hay alguna forma de lograr el mismo efecto sin tener que ejecutar dos consultas. Además, si esto no es posible, qué prefieres:

  1. SELECCIONAR + (INSERTAR o ACTUALIZAR) o
  2. ACTUALIZAR (+ INSERTAR si ACTUALIZAR falla )

Respuestas:



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

Esto requiere que la columna "ip" tenga una restricción ÚNICA (o CLAVE PRIMARIA).


EDITAR: Otra gran solución: https://stackoverflow.com/a/4330694/89771 .


2
Solo para que conste, REPLACEno es una opción.
Alix Axel

1
Con respecto al enlace "otra gran solución", también consideraría una respuesta diferente a la misma pregunta: stackoverflow.com/a/418988/3650835
KayakinKoder

19

Yo prefiero UPDATE (+ INSERT if UPDATE fails). Menos código = menos errores.


1
¡Gracias! @Sam ( stackoverflow.com/questions/418898/… ) parece estar de acuerdo contigo. También prefiero este enfoque.
Alix Axel

@Smith Me refiero a usar declaraciones simples de ACTUALIZAR e INSERTAR y verificar el valor de retorno.
Codeholic

Esto no tiene atomicidad, es posible que INSERT falle si se inserta algún otro proceso en el medio.
Robin Lavallée

7

La respuesta actual solo funcionará en sqlite OR mysql (dependiendo de si usa OR o no). Entonces, si desea compatibilidad cruzada con dbms, lo siguiente será suficiente ...

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

3
La respuesta aceptada funciona en SQLite (ese era mi objetivo). REPLACEtambién funcionará en SQLite, pero en MySQL siempre restablecerá el contador a 0; mientras que la consulta será portátil, el resultado final será muy diferente.
Alix Axel

Tienes razón, pensé que el OP estaba buscando algo que fuera portátil. Me doy cuenta de que REPLACE INTO no funcionará con todos los casos, especialmente cuando se necesita la conservación de PK, pero lo hará en muchos casos.
Jacob Thomason

Fallar limpiamente en lugar de descartar datos es una característica, no un error.
Tobu

-4

Debe usar Memcached para esto, ya que es una clave única (la dirección IP) que almacena un valor único (el número de visitas). Puede utilizar la función de incremento atómico para asegurarse de que no haya condiciones de "carrera".

Es más rápido que MySQL y ahorra carga para que MySQL pueda concentrarse en otras cosas.


Si los datos no son tan importantes, sí. Sin embargo, si esto se usa en un sitio ocupado donde muchas direcciones IP están llegando al servicio, las instancias de Memcached pueden llenarse y hacer que se elimine parte del contenido. Hacer una copia de seguridad del contenido de Memcached también sería interesante (si es necesario)
Elliot Foster

@ElliotFoster Memcached puede manejar tantos datos como la RAM que le arroje (si desea persistencia también, use redis o membase). Si recibe más de 1 millón de visitantes al día, probablemente pueda darse el lujo de darle a su instancia de Memcache más de 30 MB de RAM (que es el valor predeterminado, creo). Sin embargo, ciertamente puede manejar una carga mucho mayor que SQLite y MySQL por la cantidad de memoria que le da, simplemente no hay comparación.
Xeoncross

No confunda mi comentario con un voto en contra de Memcache, ya que creo que es una herramienta fantástica. Como es redis (no puedo hablar por membase, ya que no lo he usado). Sin embargo, memcache / redis no son las tiendas más confiables. Sí, redis tiene persistencia, pero los datos se guardan en el disco en un intervalo (la última vez que miré) y Memcache no en absoluto. Como dije, si los datos no son importantes (o se pueden reproducir fácilmente), Memcache y la compañía son excelentes. La publicación original también preguntaba sobre sqlite, que es muy diferente de MySQL y probablemente significa que están limitados de otras maneras.
Elliot Foster

Puede configurar Redis para conservar los datos tan rápido como desee (en X segundos o Y en cambios).
Buffalo
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.