更新MySQL主键


103

我有一个user_interactions包含4列的表格:

 user_1
 user_2
 type
 timestamp

主键是(user_1,user_2,type)
,我想更改为(user_2,user_1,type)

所以我所做的是:

drop primary key ...  
add primary key (user_2,user_1,type)...

瞧...

问题在于数据库在服务器上处于活动状态。

因此,在我可以更新主键之前,许多重复项已经悄悄潜入,并且它们一直在不断蔓延。

该怎么办?

我现在想做的是删除重复项,并保留最新的timestamp(表中的一列)。

然后以某种方式再次更新主键。


16
我突然为每一个被诅咒的DBA感到难过……
Ignacio Vazquez-Abrams 2010年

5
下次添加与主键具有相同列的唯一键,然后更新主键
knittl 2010年

1
@Ignacio,它存在于服务器上,但这是备份-备份服务器:-)。我不是DBA,但我不会在真正的实时服务器上尝试这个问题:-)
simplfuzz 2010年

1
@knittl,是的,这就是我现在想的,尽管很晚了:-)
simplfuzz 2010年

4
@pixeline:这是复合主键。
伊格纳西奥·巴斯克斯

Answers:


231

下次,使用单个“ alter table”语句来更新主键。

alter table xx drop primary key, add primary key(k1, k2, k3);

解决问题:

create table fixit (user_2, user_1, type, timestamp, n, primary key( user_2, user_1, type) );
lock table fixit write, user_interactions u write, user_interactions write;

insert into fixit 
select user_2, user_1, type, max(timestamp), count(*) n from user_interactions u 
group by user_2, user_1, type
having n > 1;

delete u from user_interactions u, fixit 
where fixit.user_2 = u.user_2 
  and fixit.user_1 = u.user_1 
  and fixit.type = u.type 
  and fixit.timestamp != u.timestamp;

alter table user_interactions add primary key (user_2, user_1, type );

unlock tables;

在执行此操作时,该锁应阻止进来进一步的更新。很显然,这需要多长时间取决于表的大小。

主要问题是,如果您有一些重复的时间戳都相同。


11

如果主键碰巧是auto_increment值,则必须删除自动增量,然后放下主键,然后重新添加自动增量

ALTER TABLE `xx`
MODIFY `auto_increment_field` INT, 
DROP PRIMARY KEY, 
ADD PRIMARY KEY (new_primary_key);

然后添加自动增量

ALTER TABLE `xx` ADD INDEX `auto_increment_field` (auto_increment_field),
MODIFY `auto_increment_field` int auto_increment;

然后将自动增量设置回先前的值

ALTER TABLE `xx` AUTO_INCREMENT = 5;

2

您也可以使用IGNORE关键字,例如:

 update IGNORE table set primary_field = 'value'...............
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.