重複を防ぐために、A、B、C、Dに一意のインデックスを作成したと考えて、2つのテーブルフィールドA、B、C、Dの間に挿入しました。しかし、私はどういうわけかそれらに通常のインデックスを作成しました。そのため、重複が挿入されました。 2,000万件のレコードテーブルです。
既存のインデックスを通常から一意に変更した場合、または単にA、B、C、Dの新しい一意のインデックスを追加した場合、一意のレコードが存在するため重複は削除されますか、または追加に失敗しますか?私はそれをまだテストします、それは30 milレコードであり、テーブルを台無しにしたり複製したりすることは望みません。
テーブルに重複があり、使用する場合
ALTER TABLE mytable ADD UNIQUE INDEX myindex (A, B, C, D);
クエリはエラー1062(重複キー)で失敗します。
ただし、IGNORE
を使用する場合
-- (only works before MySQL 5.7.4)
ALTER IGNORE TABLE mytable ADD UNIQUE INDEX myindex (A, B, C, D);
重複は削除されます。ただし、ドキュメントでは、保持する行を指定していません。
IGNORE
は、標準SQLのMySQL拡張機能です。新しいテーブルの一意のキーに重複がある場合、または厳格モードが有効になっているときに警告が発生する場合、ALTER TABLE
の動作を制御します。IGNORE
が指定されていない場合、重複キーエラーが発生するとコピーは中止され、ロールバックされます。IGNORE
が指定されている場合、一意のキーに重複する行の1つの行のみが使用されます。他の競合する行は削除されます。誤った値は、最も近い一致する許容値に切り捨てられます。
MySQL 5.7.4以降、ALTER TABLEのIGNORE句は削除され、その使用はエラーを生成します。
( ALTER TABLE構文 )
バージョンが5.7.4以降の場合-次のことができます。
INSERT IGNORE
(まだ利用可能です)でデータをコピーします。CREATE TABLE tmp_data SELECT * FROM mytable;
TRUNCATE TABLE mytable;
ALTER TABLE mytable ADD UNIQUE INDEX myindex (A, B, C, D);
INSERT IGNORE INTO mytable SELECT * from tmp_data;
DROP TABLE tmp_data;
IGNORE
修飾子を使用すると、INSERT
ステートメントの実行中に発生したエラーは無視されます。たとえば、IGNORE
がない場合、テーブル内の既存のUNIQUE
インデックスまたはPRIMARY KEY
値を複製する行は重複キーエラーを引き起こし、ステートメントは中止されます。IGNORE
を使用すると、行は破棄され、エラーは発生しません。無視されたエラーは、代わりに警告を生成します。
重複があると思われる場合、一意のインデックスの追加は失敗します。最初に重複があるかどうかを確認します。
select * from
(select a,b,c,d,count(*) as n from table_name group by a,b,c,d) x
where x.n > 1
これは20M行の高価なクエリかもしれませんが、すべての重複キーを取得するため、プライマリインデックスを追加できません。サブクエリでwhereを実行すると、これを小さなチャンクに分割できます:where a='some_value'
取得したレコードについては、行を一意にするために何かを変更する必要があります。それが完了したら(クエリは0行を返します)、プライマリインデックスを追加しても安全です。
IGNOREの代わりにON DUPLICATE KEY UPDATEを使用すると、どの値を優先するかを制御できます。
質問に答えるには、重複する値を持つ列にUNIQUE
制約を追加するとエラーがスローされます。
たとえば、次のスクリプトを試すことができます。
CREATE TABLE `USER` (
`USER_ID` INT NOT NULL,
`USERNAME` VARCHAR(45) NOT NULL,
`NAME` VARCHAR(45) NULL,
PRIMARY KEY (`USER_ID`));
INSERT INTO USER VALUES(1,'Apple', 'woz'),(2,'Apple', 'jobs'),
(3,'google', 'sergey'),(4,'google', 'larry');
ALTER TABLE `USER`
ADD UNIQUE INDEX `USERNAME_UNIQUE` (`USERNAME` ASC);
/*
Operation failed: There was an error while applying the SQL script to the database.
ERROR 1062: Duplicate entry 'Apple' for key 'USERNAME_UNIQUE'
*/