我在两个表格A,B,C,D之间插入,相信我在A,B,C,D上创建了一个唯一索引以防止重复。但是我不知何故简单地在那些上做了一个正常的索引。所以插入了重复项。这是2000万的记录表。
如果我将现有索引从正常更改为唯一,或者只是为A,B,C添加新的唯一索引,D将删除重复项,或者因为存在唯一记录而添加失败?我测试它是30密耳的记录,我不想弄乱桌子或复制它。
答案 0 :(得分:47)
如果表格中有重复项,则使用
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
,则只使用行的一行 复制一个唯一的密钥。其他冲突的行将被删除。 不正确的值被截断为最接近的匹配可接受 值。
从MySQL 5.7.4开始,删除了ALTER TABLE的IGNORE子句 它的使用会产生错误。
如果您的版本是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
,该行被丢弃,不会发生错误。忽略错误 而是生成警告。
另请参阅:INSERT ... SELECT Syntax和Comparison of the IGNORE Keyword and Strict SQL Mode
答案 1 :(得分:4)
如果您认为会有重复项,添加唯一索引将失败。 首先检查有哪些重复:
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 a='some_value'
对于检索到的记录,您必须更改某些内容以使行唯一。如果这样做(查询返回0行),您应该可以安全地添加主索引。
答案 2 :(得分:1)
您可以使用ON DUPLICATE KEY UPDATE而不是IGNORE,这样可以控制哪些值占优势。
答案 3 :(得分:0)
要回答您的问题 - 在具有重复值的列上添加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'
*/