2010-02-26 3 views
62

У меня есть таблица user_interactions с 4-мя колонками:Обновление MySQL первичный ключ

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)... 

и voila ...

Проблема в том, что база данных находится в прямом эфире на сервере.

Поэтому, прежде чем я мог бы обновить первичный ключ, многие дублируют уже закрались, и они постоянно ползучая.

Что делать?

Теперь я хочу удалить дубликаты и сохранить их с последним timestamp (который является столбцом в таблице).

И затем как-нибудь обновить первичный ключ снова.

+8

я вдруг чувствую себя плохо для каждого DBA Я проклял себе под нос ... –

+3

в следующий раз добавьте уникальный ключ с теми же столбцами, что и первичный ключ, затем обновите первичный ключ – knittl

+0

@ignacio tee hee – benlumley

ответ

150

В следующий раз использовать один «изменить таблицу» заявление, чтобы обновить первичный ключ.

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; 

замок должен прекратить дальнейшие обновления, поступающие в то время как ваши делают это. Как долго это занимает, очевидно, зависит от размера вашей таблицы.

Основная проблема заключается в том, что у вас есть дубликаты с одинаковой меткой времени.

+1

Вы здорово! Хотел бы я поблагодарить вас. – dharm0us

2

Вы можете использовать ключевое слово IGNORE тоже пример:

update IGNORE table set primary_field = 'value'............... 
+0

Он пытается изменить столбец, а не обновлять значение. –

4

Если первичный ключ случается значение 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; 
Смежные вопросы