Yo recomendaría usar INSERT...ON DUPLICATE KEY UPDATE
.
Si lo usa INSERT IGNORE
, la fila no se insertará realmente si da como resultado una clave duplicada. Pero la declaración no generará un error. Genera una advertencia en su lugar. Estos casos incluyen:
- Insertar una clave duplicada en columnas con
PRIMARY KEY
o UNIQUE
restricciones.
- Insertar un NULL en una columna con una
NOT NULL
restricción.
- Insertar una fila en una tabla particionada, pero los valores que inserte no se asignan a una partición.
Si lo usa REPLACE
, MySQL en realidad hace un DELETE
seguimiento INSERT
interno, que tiene algunos efectos secundarios inesperados:
- Se asigna una nueva ID de incremento automático.
- Las filas dependientes con claves foráneas pueden eliminarse (si utiliza claves foráneas en cascada) o, de lo contrario, evitar
REPLACE
.
- Los disparadores que disparan
DELETE
se ejecutan innecesariamente.
- Los efectos secundarios también se propagan a las réplicas.
Corrección: tanto REPLACE
y INSERT...ON DUPLICATE KEY UPDATE
no son estándar, las invenciones de propiedad específica a MySQL. ANSI SQL 2003 define una MERGE
declaración que puede resolver la misma necesidad (y más), pero MySQL no admite la 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 se genera la nueva identificación , 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 que AUTO_INCREMENT=3
indica que se generó una identificación, pero que no se utilizó en la fila.
Mientras REPLACE
que elimina la fila original e inserta una nueva fila, generando y almacenando 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 |
+----+------+
INSERT ... ON DUPLICATE KEY UPDATE ...
declaraciones. Muchos de los datos están duplicados, y ha dado como resultado que una instancia de AI PK aumente de 17,029,941 a 46,271,740 entre dos filas. Esa generación de una nueva IA cada vez significa que su rango puede llenarse muy rápidamente y necesita limpiar. ¡Esta mesa tiene solo dos semanas!En caso de que quiera ver qué significa todo esto, aquí hay un golpe de golpe de todo:
La clave primaria se basa en ambas columnas de esta tabla de referencia rápida. Una clave primaria requiere valores únicos.
Vamos a empezar:
tenga en cuenta que lo anterior ahorró demasiado trabajo extra al configurar la columna igual a sí misma, no se necesita ninguna actualización
y ahora algunas pruebas de varias filas:
no se generaron otros mensajes en la consola, y ahora tiene esos 4 valores en los datos de la tabla. Eliminé todo excepto (1,1) para poder probar desde el mismo campo de juego
Entonces ahí lo tienes. Como todo esto se realizó en una tabla nueva con casi ningún dato y no en producción, los tiempos de ejecución fueron microscópicos e irrelevantes. Cualquier persona con datos del mundo real sería más que bienvenido a contribuir.
fuente
INSERT IGNORE INTO users_partners (uid,pid) VALUES (1,1),(1,2),(1,3),(1,4)
.Algo importante para agregar: ¡Al usar INSERT IGNORE y usted tiene violaciones clave, MySQL NO genera una advertencia!
Si intenta, por ejemplo, insertar 100 registros a la vez, con uno defectuoso, entraría en modo interactivo:
Como ves: ¡Sin advertencias! Este comportamiento incluso se describe erróneamente en la documentación oficial de Mysql.
Si su script necesita ser informado, si algunos registros no se han agregado (debido a violaciones de claves), debe llamar a mysql_info () y analizarlo para obtener el valor "Duplicados".
fuente
mysqli_affected_rows()
para saber siINSERT
realmente sucedió.Cannot add or update a child row: a foreign key constraint fails
y no hay filas se añaden (incluso los válidos).INSERT IGNORE
, las claves duplicadas se ignoran sin error ni advertencia.Yo uso habitualmente
INSERT IGNORE
, y también parece exactamente el tipo de comportamiento que estás buscando. Siempre y cuando sepa que las filas que causarían conflictos de índice no se insertarán y planifique su programa en consecuencia, no debería causar ningún problema.fuente
Sé que esto es antiguo, pero agregaré esta nota en caso de que alguien más (como yo) llegue a esta página mientras trato de encontrar información sobre INSERTAR .. REGISTRARSE.
Como se mencionó anteriormente, si usa INSERT..IGNORE, los errores que se producen al ejecutar la instrucción INSERT se tratan como advertencias.
Una cosa que no se menciona explícitamente es que INSERT..IGNORE hará que los valores no válidos se ajusten a los valores más cercanos cuando se inserten (mientras que los valores no válidos causarían que la consulta se cancelara si no se usaba la palabra clave IGNORE).
fuente
ON DUPLICATE KEY UPDATE no está realmente en el estándar. Es casi tan estándar como REPLACE. Ver SQL MERGE .
Esencialmente, ambos comandos son versiones de sintaxis alternativa de los comandos estándar.
fuente
Replace
En parece una opción. O puedes consultar conEsto insertará o eliminará y luego insertará. Tiendo a ir por un
IF NOT EXISTS
cheque primero.fuente
REPLACE
borra todas las filas de la tabla con cualquier teclaPRIMARY
o coincidenteUNIQUE
, entoncesINSERTs
. Potencialmente, esto es mucho más trabajo que IODKU.Posible peligro de INSERTAR IGNORE. Si está intentando insertar el valor VARCHAR durante más tiempo, la columna se definió con: el valor se truncará y se insertará INCLUSO SI el modo estricto está habilitado.
fuente
Si utiliza
insert ignore
tener unaSHOW WARNINGS;
declaración al final de su conjunto de consultas, se mostrará una tabla con todas las advertencias, incluidos los ID que fueron duplicados.fuente
SHOW WARNINGS;
solo parece afectar la última consulta. Las declaraciones anteriores no se acumulan, si tiene más de una declaración.Si desea insertar en la tabla y en el conflicto de la clave primaria o índice único, actualizará la fila en conflicto en lugar de insertar esa fila.
Sintaxis:
Ahora aquí, esta declaración de inserción puede verse diferente a lo que has visto anteriormente. Esta instrucción de inserción intenta insertar una fila en la tabla1 con el valor de ayb en la columna columna1 y columna2 respectivamente.
Comprendamos esta declaración en profundidad:
Por ejemplo: aquí la columna1 se define como la clave principal en la tabla1.
Ahora, si en la tabla 1 no hay una fila que tenga el valor "a" en la columna 1. Entonces, esta instrucción insertará una fila en la tabla1.
Ahora, si en la tabla 1 hay una fila que tiene el valor "a" en la columna 2. Entonces, esta declaración actualizará el valor de la columna2 de la fila con "c" donde el valor de la columna1 es "a".
Entonces, si desea insertar una nueva fila, de lo contrario, actualice esa fila en el conflicto de la clave primaria o el índice único.
Lea más en este enlace
fuente
INSERT...ON DUPLICATE KEY UPDATE
se prefiere para evitar la gestión de excepciones inesperadas.Esta solución funciona cuando tiene ** 1 restricción única ** solamente
En mi caso, lo sé
col1
ycol2
hago un índice compuesto único.Realiza un seguimiento del error, pero no arroja una excepción en duplicado. En cuanto al rendimiento, la actualización por el mismo valor es eficiente ya que MySQL lo nota y no lo actualiza.
La idea de utilizar este enfoque surgió de los comentarios en phpdelusions.net/pdo .
fuente