Recomendaría usar INSERT...ON DUPLICATE KEY UPDATE
.
Si usa INSERT IGNORE
, la fila no se insertará realmente si da como resultado una clave duplicada. Pero la declaración no generará un error. En su lugar, genera una advertencia. Estos casos incluyen:
- Insertar una clave duplicada en columnas con
PRIMARY KEY
oUNIQUE
restricciones - Insertar un NULL en una columna con un
NOT NULL
restricción. - Insertar una fila en una tabla particionada, pero los valores que inserta no se asignan a una partición.
Si usa REPLACE
, MySQL en realidad hace un DELETE
seguido de INSERT
internamente, lo que tiene algunos efectos secundarios inesperados:
- Se asigna un nuevo ID de incremento automático.
- Las filas dependientes con claves foráneas pueden eliminarse (si usa claves foráneas en cascada) o evitar el
REPLACE
. - Disparadores que se disparan en
DELETE
se ejecutan innecesariamente. - Los efectos secundarios también se propagan a las réplicas.
corrección: ambos REPLACE
y INSERT...ON DUPLICATE KEY UPDATE
son invenciones patentadas no estándar específicas de MySQL. ANSI SQL 2003 define un MERGE
declaración que puede resolver la misma necesidad (y más), pero MySQL no es compatible con MERGE
declaración.
Un usuario intentó editar esta publicación (los moderadores rechazaron la edición). La edición intentó agregar un reclamo que INSERT...ON DUPLICATE KEY UPDATE
hace que se asigne una nueva identificación de incremento automático. Es cierto que la nueva identificación es generada , pero no se usa en la fila modificada.
Vea la demostración a continuación, probada con Percona Server 5.5.28. La variable de configuración innodb_autoinc_lock_mode=1
(el valor predeterminado):
mysql> create table foo (id serial primary key, u int, unique key (u));
mysql> insert into foo (u) values (10);
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 10 |
+----+------+
mysql> show create table foo\G
CREATE TABLE `foo` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`u` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `u` (`u`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
mysql> insert into foo (u) values (10) on duplicate key update u = 20;
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 20 |
+----+------+
mysql> show create table foo\G
CREATE TABLE `foo` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`u` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `u` (`u`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
Lo anterior demuestra que la instrucción IODKU detecta el duplicado e invoca la actualización para cambiar el valor de u
. Tenga en cuenta el AUTO_INCREMENT=3
indica que se generó una identificación, pero no se usó en la fila.
Mientras que REPLACE
elimina la fila original e inserta una nueva fila, generando y almacenar una nueva identificación de incremento automático:
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 20 |
+----+------+
mysql> replace into foo (u) values (20);
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 3 | 20 |
+----+------+