He encontrado algunas soluciones "serían" para el clásico "¿Cómo inserto un nuevo registro o actualizo uno si ya existe?", Pero no puedo hacer que ninguno de ellos funcione en SQLite.
Tengo una tabla definida de la siguiente manera:
CREATE TABLE Book
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Name VARCHAR(60) UNIQUE,
TypeID INTEGER,
Level INTEGER,
Seen INTEGER
Lo que quiero hacer es agregar un registro con un Nombre único. Si el nombre ya existe, quiero modificar los campos.
¿Alguien puede decirme cómo hacer esto, por favor?
Respuestas:
Echa un vistazo a http://sqlite.org/lang_conflict.html .
Quieres algo como:
Tenga en cuenta que cualquier campo que no esté en la lista de inserción se establecerá en NULL si la fila ya existe en la tabla. Esta es la razón por la cual hay una subselección para la
ID
columna: en el caso de reemplazo, la instrucción lo establecería en NULL y luego se asignaría una nueva ID.Este enfoque también se puede usar si desea dejar solo valores de campo particulares si la fila en el caso de reemplazo pero establece el campo en NULL en el caso de inserción.
Por ejemplo, suponiendo que quiere dejarlo
Seen
solo:fuente
Level
, este enfoque no puede seguirse.Debe usar el
INSERT OR IGNORE
comando seguido de unUPDATE
comando: en el siguiente ejemploname
hay una clave principal:El primer comando insertará el registro. Si el registro existe, ignorará el error causado por el conflicto con una clave primaria existente.
El segundo comando actualizará el registro (que ahora definitivamente existe)
fuente
Debe establecer una restricción en la tabla para desencadenar un " conflicto " que luego resuelve haciendo un reemplazo:
Entonces puedes emitir:
El "SELECCIONAR * DE los datos" le dará:
Tenga en cuenta que data.id es "3" y no "1" porque REPLACE hace un BORRAR e INSERTAR, no una ACTUALIZACIÓN. Esto también significa que debe asegurarse de definir todas las columnas necesarias o obtendrá valores NULL inesperados.
fuente
En primer lugar actualizarlo. Si el recuento de filas afectado = 0, insértelo. Es el más fácil y adecuado para todos los RDBMS .
fuente
Insert or Replace
Es realmente más preferible.INSERT OR REPLACE
reemplazará los otros campos al valor predeterminado.Si quieres preservar el otro campo
o usando UPSERT (la sintaxis se agregó a SQLite con la versión 3.24.0 (2018-06-04))
El
excluded.
prefijo igual al valor enVALUES
.fuente
Upsert es lo que quieres.
UPSERT
La sintaxis se agregó a SQLite con la versión 3.24.0 (2018-06-04).Tenga en cuenta que en este punto la palabra real "UPSERT" no es parte de la sintaxis upsert.
La sintaxis correcta es
INSERT INTO ... ON CONFLICT(...) DO UPDATE SET...
y si está haciendo
INSERT INTO SELECT ...
su selección, necesita al menosWHERE true
resolver la ambigüedad del analizador sobre el tokenON
con la sintaxis de unión.Tenga en cuenta que
INSERT OR REPLACE...
eliminará el registro antes de insertar uno nuevo si tiene que reemplazarlo, lo que podría ser malo si tiene cascadas de clave externa u otros desencadenantes de eliminación.fuente
UPSERT
sintaxis.Si no tiene una clave principal, puede insertarla si no existe y luego realizar una actualización. La tabla debe contener al menos una entrada antes de usar esto.
fuente
Creo que quieres UPSERT .
"INSERTAR O REEMPLAZAR" sin el truco adicional en esa respuesta restablecerá los campos que no especifique a NULL u otro valor predeterminado. (Este comportamiento de INSERTAR O REEMPLAZAR es diferente a ACTUALIZAR; es exactamente como INSERTAR, porque en realidad es INSERTAR; sin embargo, si lo que desea es ACTUALIZAR si existe, probablemente desee la semántica ACTUALIZAR y se sorprenderá desagradablemente por el resultado real).
El truco de la implementación sugerida de UPSERT es básicamente usar INSERTAR O REEMPLAZAR, pero especificar todos los campos, usando cláusulas SELECT incrustadas para recuperar el valor actual de los campos que no desea cambiar.
fuente
Creo que vale la pena señalar que puede haber algún comportamiento inesperado aquí si no comprende a fondo cómo interactúan PRIMARY KEY y UNIQUE .
Como ejemplo, si desea insertar un registro solo si el campo NOMBRE no se toma actualmente, y si es así, desea que se active una excepción de restricción, entonces INSERTAR O REEMPLAZAR no arrojará una excepción y en su lugar lo hará. resuelva la restricción ÚNICA reemplazando el registro en conflicto (el registro existente con el mismo NOMBRE ). Gaspard lo demuestra muy bien en su respuesta anterior.
Si desea que se active una excepción de restricción, debe usar una instrucción INSERT y confiar en un comando UPDATE separado para actualizar el registro una vez que sepa que no se toma el nombre.
fuente