修复表中的重复条目

时间:2011-12-12 21:40:01

标签: mysql auto-increment unique-index

我刚刚发现我的生产服务器上的表(包含大约35K条记录)在INT(11)列中包含588个具有AUTO_INCREMENT的重复条目。 该列上缺少UNIQUE键,因此可能是原因。

有关如何为所有重复条目提供唯一ID,然后将UNIQUE键添加到列中以便永远不会再发生的任何想法?

表架构:

CREATE TABLE `items` (
 `item_ID` int(11) unsigned NOT NULL auto_increment,
 `u_ID` int(10) NOT NULL default '0',
 `user_ID` int(11) NOT NULL default '0',
 `p_ID` tinyint(4) NOT NULL default '0',
 `url` varchar(255) NOT NULL,
 `used` int(10) unsigned NOT NULL,
 `sort` tinyint(4) NOT NULL,
 `last_checked` int(11) NOT NULL,
 `unixtime` int(11) NOT NULL,
 `switched` int(11) NOT NULL,
 `active` tinyint(1) NOT NULL default '0',
 UNIQUE KEY `unique` (`p_ID`,`url`),
 KEY `index` (`u_ID`,`item_ID`,`sort`,`active`),
 KEY `index2` (`u_ID`,`switched`,`active`),
 KEY `item_ID` (`item_ID`),
 KEY `p_ID` (`p_ID`),
 KEY `u_ID` (`u_ID`)
) ENGINE=MyISAM AUTO_INCREMENT=42755 DEFAULT CHARSET=utf8

3 个答案:

答案 0 :(得分:2)

这样的事情怎么样?再次在备份上再次测试它。

# Copy duplicate records
CREATE TABLE newitem SELECT * FROM items WHERE item_ID IN 
    (SELECT item_ID FROM itemd GROUP BY item_ID HAVING COUNT(*) > 1);

# remove auto increment from id in new table
ALTER TABLE newitem DROP INDEX Item_ID, MODIFY item_ID int;

# delete duplicates from original
DELETE FROM item WHERE item_ID IN (SELECT DISTINCT item_ID FROM newitem);

#Update column to be primary key
ALTER TABLE items DROP INDEX Item_ID, ADD PRIMARY KEY (Item_ID);

# Set new duplicate ID's to null
UPDATE newitem SET item_ID=NULL;

# Insert records back into old table
INSERT INTO item SELECT * FROM newitem;

# Get rid of work table
DROP newitem;

答案 1 :(得分:2)

由于表格上已有UNIQUE密钥,您可以使用此密钥生成UPDATE语句,为item_id重新分配唯一ID:

UPDATE
        items AS it
    JOIN
        ( SELECT 
              i.p_ID, i.url, @id:= @id+1 AS id
          FROM 
                  items AS i  
              CROSS JOIN 
                  ( SELECT @id:=0 ) AS dummy
          ORDER BY
              i.p_ID, i.url
        ) AS unq
      ON 
      (unq.p_ID, unq.url) = (it.p_ID, it.url)
SET 
    it.item_id = unq.id ;

然后,您可以在item_id

上添加唯一索引

答案 2 :(得分:1)

有趣。你有一个没有主键引用的auto_increment,只有一个索引,这就是你首先拥有dupes的原因。如果您尝试更新并分配primary key (item_ID),MySQL会因为item_ID列中的欺骗而抱怨。

您的引擎是MyISAM,这意味着您没有任何FK约束,因此您可以执行表的mysqldump,截断表,更新架构,然后重新导入数据。重新导入时,MySQL应正确插入具有真正唯一Item_Ids的所有行。

我将概述此处的步骤,但我强烈建议您在开发环境中执行此操作,以确认步骤在应用于您的生产环境之前正常工作。我对borked生产数据不承担任何责任:)

$ mysqldump -u <user_name> -h <db_host> --opt <database_name> --single-transaction > backup.sql

mysql> truncate table `items`;

mysql> ALTER TABLE `items` DROP INDEX `Item_ID`, ADD PRIMARY KEY (`item_ID`), AUTO_INCREMENT = 1;

$ vi backup.sql # Remove the AUTO_INCREMENT reference from the Create Table syntax

$ mysql -h <host_name> <db_name> -u <username> -p < backup.sql    

试一试,这些步骤未经测试,但应该让你走上正确的道路。