Mysql 修复表中的重复项

Mysql 修复表中的重复项,mysql,auto-increment,unique-index,Mysql,Auto Increment,Unique Index,我刚刚发现我的生产服务器上的一个表(包含大约35K条记录)在一个INT(11)列中包含588个重复条目,该列具有自动增量。 该列上缺少唯一键,因此这可能是原因 关于如何给所有重复的条目一个唯一的ID,然后将唯一的键添加到列中,这样就不会再发生这种情况,您有什么想法吗 表架构: CREATE TABLE `items` ( `item_ID` int(11) unsigned NOT NULL auto_increment, `u_ID` int(10) NOT NULL default '0

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

关于如何给所有重复的条目一个唯一的ID,然后将唯一的键添加到列中,这样就不会再发生这种情况,您有什么想法吗

表架构:

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

有趣。您有一个自动增量,没有主键引用,只有一个索引,这就是为什么您首先有重复。如果您尝试更新并分配
主键(item\u ID)
MySQL会因为item\u ID列中的重复而抱怨

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

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

$mysqldump-u-h--opt--single transaction>backup.sql
mysql>截断表'items';
mysql>更改表`items`删除索引`Item\u ID`,添加主键(`Item\u ID`),自动增量=1;
$vi backup.sql#从创建表语法中删除自动增量引用
$mysql-h-u-p

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

像这样的方法怎么样?首先在备份上再次测试它

# 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;

由于表上已经有一个
UNIQUE
键,因此可以使用该键生成一个
UPDATE
语句,将唯一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\u id

上添加一个唯一索引。在自动增量列上不需要唯一键,它必须在
show create table
中标识为主键。你能发布你的模式吗?不知道如何获得一个好的模式
DESC tablename
在phpMyAdmin中不能很好地输出它你可以访问服务器吗?您可以从mysql cli发出命令:
show create table
。我很想知道你是如何将一个自动增量添加到一个列中而不被识别为
主键(
id
你可以拥有一个非主键的自动增量。它所需要的只是一个简单的索引。如果
item\u id
没有在其他表中用作外键,您只需删除该列并将其重新创建为
AUTO\u INCREMENT主键
,这将重新生成item\u id的右键?我想保留我的当前ID,并且只使用具有重复ID的新ID更新记录。我可以在PHP中使用while循环来检查记录是否重复,并使用
MAX(item_ID)
给它一个新的ID,但听起来有可能会重新生成它们。如果是这种情况,那么您可以编写一个应用程序,通过ID循环,识别重复,然后为重复分配新值。然后,当分配了新的值时,运行alter语句以指示
Item_ID
是一个
主键,而不仅仅是一个索引。在表的副本上对其进行测试,它似乎工作正常!谢谢很高兴它起作用了-只需注意@ypercube答案要优雅得多。这并不是完全正确的。它使用
item_ID='0'
@ThomasGG生成数千条记录:是的,有一个小错误,现在编辑。再试一次。
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 ;