MySQL: ALTER IGNORE TABLE da "Violación de restricción de integridad"

I'm trying to remove duplicates from a MySQL table using ALTER IGNORE TABLE + an UNIQUE KEY. The MySQL documentation says:

IGNORE es una extensión de MySQL para SQL estándar. Controla cómo funciona ALTER TABLE si hay duplicados en claves únicas en la nueva tabla o si ocurren advertencias cuando el modo estricto está habilitado. Si no se especifica IGNORE, la copia se cancela y se revierte si se producen errores de clave duplicada. Si se especifica IGNORE, solo se usa la primera fila de las filas con duplicados en una clave única. Las otras filas en conflicto se eliminan. Los valores incorrectos se truncan al valor aceptable coincidente más cercano.

When I run the query ...

ALTER IGNORE TABLE table ADD UNIQUE INDEX dupidx (field)

... I still get the error #1062 - Duplicate entry 'blabla' for key 'dupidx'.

preguntado el 08 de noviembre de 11 a las 16:11

3 Respuestas

La IGNORE keyword extension to MySQL seems to have a bug in the InnoDB version on some version of MySQL.

You could always, convert to MyISAM, IGNORE-ADD the index and then convert back to InnoDB

ALTER TABLE table ENGINE MyISAM;
ALTER IGNORE TABLE table ADD UNIQUE INDEX dupidx (field);
ALTER TABLE table ENGINE InnoDB;

Note, if you have Foreign Key constraints this will not work, you will have to remove those first, and add them back later.

Respondido 16 Feb 13, 23:02

In that link to the InnoDB bug there is a suggested workaround to first run set session old_alter_table=1; Esto funcionó para mí. - Peter

Thanks Peter - this seems to be working for me now. Had no idea of this problem - my dev machine is mariadb but when I had to run on production (mysql 5.5) ran into this. This stackoverflow saved my day! - spidie

This is quite possibly the worst accepted answer I've ever seen on Stack Overflow. Changing storage engines is a significant undertaking in itself with even medium-sized tables. These three queries could potentially lock up a database server for hours. This is nothing like a solution. - Mikkel

I think I was a little bit sick just then - John Hunt

Or try set session old_alter_table=1 (Don't forget to set it back!)

Ver: http://mysqlolyk.wordpress.com/2012/02/18/alter-ignore-table-add-index-always-give-errors/

Respondido 31 Jul 13, 18:07

This did work for me. It's lengthy on big tables, but it seems fairly linear. On my machine, it was able to process roughly 2GiB of data per hour, which was about two days. I wonder how that compares to the accepted solution, which was to convert to myISAM, add the index and convert back. - Chris Strickland

Beware! If you're using replication, the old_alter_table setting doesn't replicate, so the ALTER TABLE IGNORE will fail on the slave and break replication. To fix this, I performed the ALTER manually on the slave, then skipped the offending ALTER TABLE mediante el uso SET GLOBAL sql_slave_skip_counter = 1, then resumed replication. - entoncesickdude

The problem is that you have duplicate data in the field you're trying to index. You'll need to remove the offending duplicates before you can add a unique index.

Una forma es hacer lo siguiente:

   CREATE TABLE tmp_table LIKE table;
   ALTER IGNORE TABLE tmp_table ADD UNIQUE INDEX dupidx (field);
   INSERT IGNORE INTO tmp_table SELECT * FROM table;
   DROP TABLE table;
   RENAME TABLE tmp_table TO table;

this allows you to insert only the unique data into the table

respondido 08 nov., 11:21

No, the IGNORE keyword should take care of those duplicates. That would be the beauty of this solution. See the cited docs in my question. - Philippe Gerber

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.