2

運用サーバーのテーブル (約 35K レコードを保持) の INT(11) 列に、AUTO_INCREMENT を持つ 588 個​​の重複エントリが含まれていることがわかりました。その列には 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
4

3 に答える 3

2

UNIQUEテーブルには既にキーがあるため、これを使用して、UPDATE一意の ID を に再割り当てするステートメントを作成できitem_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

于 2011-12-12T22:56:45.523 に答える
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;
于 2011-12-12T22:48:35.223 に答える
1

面白い。主キー参照のない auto_increment があります。インデックスだけです。これが、そもそも重複がある理由です。更新して割り当てようとするとprimary key (item_ID)、item_ID 列の重複が原因で MySQL が文句を言います。

エンジンは MyISAM です。つまり、FK 制約がないため、テーブルの mysqldump を実行し、テーブルを切り捨て、スキーマを更新してから、データを再インポートできます。再インポートすると、MySQL は真に一意の Item_Ids を持つすべての行を正しく挿入する必要があります。

ここで手順の概要を説明しますが、運用環境に適用する前に、開発環境でこれを実行して、手順が正しく機能することを確認することを強くお勧めします。私は壊れた生産データについて一切の責任を負いません :)

$ 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    

これらの手順はテストされていませんが、正しい道をたどることができます。

于 2011-12-12T22:29:58.247 に答える