sqlite - tiempo - mysql insert on duplicate update
¿INSERTAR SI NO EXISTE OTRA ACTUALIZACIÓN? (9)
"Upsert" es lo que quieres. https://www.sqlite.org/lang_UPSERT.html
La sintaxis de UPSERT se agregó a SQLite con la versión 3.24.0 (2018-06-04).
CREATE TABLE phonebook2( name TEXT PRIMARY KEY, phonenumber TEXT, validDate DATE ); INSERT INTO phonebook2(name,phonenumber,validDate) VALUES(''Alice'',''704-555-1212'',''2018-05-08'') ON CONFLICT(name) DO UPDATE SET phonenumber=excluded.phonenumber, validDate=excluded.validDate WHERE excluded.validDate>phonebook2.validDate;
Tenga en cuenta que, en este punto, la palabra real "UPSERT" no forma parte de la sintaxis superior.
La sintaxis correcta es
INSERT INTO ... ON CONFLICT(...) DO UPDATE SET...
y si está haciendo INSERT INTO SELECT ...
su selección necesita al menos WHERE true
para resolver la ambigüedad del analizador sobre el token ON
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 incorrecto si tiene cascadas de clave externa u otros activadores de eliminación.
He encontrado algunas soluciones "para los clásicos" "¿Cómo inserto un nuevo registro o actualizo uno si ya existe?", Pero no consigo 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?
Creo que quieres UPSERT .
"INSERTAR O REEMPLAZAR" sin el engaño adicional en esa respuesta restablecerá los campos que no especifique en NULL u otro valor predeterminado. (Este comportamiento de INSERT O REPLACE es diferente a UPDATE; es exactamente igual a INSERT, porque en realidad es INSERT; sin embargo, si lo que desea es UPDATE-si-existe, probablemente desee la semántica UPDATE y el resultado real le sorprenderá desagradablemente).
El engaño de la implementación sugerida de UPSERT consiste básicamente en utilizar 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.
Creo que vale la pena señalar que puede haber un comportamiento inesperado aquí si no entiendes completamente cómo interactúan PRIMARY KEY y UNIQUE .
Como ejemplo, si desea insertar un registro solo si el campo NOMBRE no se ha tomado actualmente, y si lo está, desea que se active una excepción de restricción, entonces INSERTAR O REEMPLAZAR no lanzará una excepción y en su lugar resuelva la propia restricción UNIQUE reemplazando el registro conflictivo (el registro existente con el mismo NOMBRE ). demuestra muy bien en su respuesta anterior.
Si desea que se active una excepción de restricción, debe utilizar una instrucción INSERT y confiar en un comando UPDATE por separado para actualizar el registro una vez que sepa que no se tomó el nombre.
Debe establecer una restricción en la tabla para desencadenar un " conflict " que luego resuelve haciendo un reemplazo:
CREATE TABLE data (id INTEGER PRIMARY KEY, event_id INTEGER, track_id INTEGER, value REAL);
CREATE UNIQUE INDEX data_idx ON data(event_id, track_id);
Entonces puedes emitir:
INSERT OR REPLACE INTO data VALUES (NULL, 1, 2, 3);
INSERT OR REPLACE INTO data VALUES (NULL, 2, 2, 3);
INSERT OR REPLACE INTO data VALUES (NULL, 1, 2, 5);
El "SELECT * FROM data" le dará:
2|2|2|3.0
3|1|2|5.0
Tenga en cuenta que el 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 que define todas las columnas necesarias o obtendrá valores NULL inesperados.
Debe usar el comando INSERT OR IGNORE
seguido de un comando UPDATE
: En el siguiente ejemplo, el name
es una clave principal:
INSERT OR IGNORE INTO my_table (name, age) VALUES (''Karen'', 34)
UPDATE my_table SET age = 34 WHERE name=''Karen''
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)
Eche un vistazo a http://sqlite.org/lang_conflict.html .
Quieres algo como:
insert or replace into Book (ID, Name, TypeID, Level, Seen) values
((select ID from Book where Name = "SearchName"), "SearchName", ...);
Tenga en cuenta que cualquier campo que no esté en la lista de inserción se establecerá en NULO si la fila ya existe en la tabla. Esta es la razón por la que hay una subselección para la columna de ID
: en el caso de reemplazo, la declaración lo establecerá en NULL y luego se asignará una ID nueva.
Este enfoque también se puede usar si desea dejar valores de campo particulares solo si la fila en el caso de reemplazo, pero establezca el campo en NULO en el caso de inserción.
Por ejemplo, suponiendo que quiere dejarlo Seen
solo:
insert or replace into Book (ID, Name, TypeID, Level, Seen) values (
(select ID from Book where Name = "SearchName"),
"SearchName",
5,
6,
(select Seen from Book where Name = "SearchName"));
En primer lugar actualizarlo. Si el recuento de filas afectadas es 0, insértelo. Es el más fácil y adecuado para todos los RDBMS .
Si no tiene una clave principal, puede insertar, si no existe, y luego hacer una actualización. La tabla debe contener al menos una entrada antes de usar esto.
INSERT INTO Test
(id, name)
SELECT
101 as id,
''Bob'' as name
FROM Test
WHERE NOT EXISTS(SELECT * FROM Test WHERE id = 101 and name = ''Bob'') LIMIT 1;
Update Test SET id=''101'' WHERE name=''Bob'';
INSERT OR REPLACE
reemplazará los otros campos ( TypeID
, Level
) al valor predeterminado.
INSERT OR REPLACE INTO book(id, name) VALUES(1001, ''Programming'')
Estoy usando esto
INSERT OR IGNORE INTO book(id) VALUES(1001);
UPDATE book SET name = ''Programming'' WHERE id = 1001;
También puedes usar
INSERT OR REPLACE INTO book (id, name)
VALUES (1001, ''Programming'',
(SELECT typeid FROM book WHERE id = 1001),
(SELECT level FROM book WHERE id = 1001),
)
Pero creo que el primer método más fácil de leer.