Aktualizacja klucza podstawowego MySQL


103

Mam tabelę user_interactionsz 4 kolumnami:

 user_1
 user_2
 type
 timestamp

Klucz podstawowy to (user_1,user_2,type)
i chcę zmienić na(user_2,user_1,type)

Więc co zrobiłem to:

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

i voila ...

Problem polega na tym, że baza danych działa na serwerze.

Więc zanim mogłem zaktualizować klucz podstawowy, wiele duplikatów już wkradło się i wciąż się wkradają.

Co robić?

Chcę teraz usunąć duplikaty i zachować te z najnowszymi timestamp(czyli kolumną w tabeli).

A potem jakoś ponownie zaktualizuj klucz podstawowy.


16
Nagle czuję się źle z powodu każdego DBA, którego przeklinałem pod nosem ...
Ignacio Vazquez-Abrams

5
następnym razem dodaj unikalny klucz z tymi samymi kolumnami co klucz podstawowy, a następnie zaktualizuj klucz podstawowy
knittl

1
@Ignacio, jest na żywo na serwerze, ale to jest serwer zapasowy :-). Nie jestem DBA, ale nie spróbuję tego na NAPRAWDĘ live serwerze :-)
simplfuzz

1
@knittl, tak właśnie myślałem, ale bardzo późno :-)
simplfuzz

4
@pixeline: To złożony klucz podstawowy.
Ignacio Vazquez-Abrams

Odpowiedzi:


231

Następnym razem użyj pojedynczej instrukcji „alter table”, aby zaktualizować klucz podstawowy.

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

Aby naprawić rzeczy:

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;

Blokada powinna zatrzymać dalsze aktualizacje, gdy to robisz. Jak długo to potrwa, zależy oczywiście od wielkości twojego stołu.

Główny problem polega na tym, że masz kilka duplikatów z tą samą sygnaturą czasową.


11

Jeśli klucz podstawowy ma wartość auto_increment, musisz usunąć automatyczną inkrementację, a następnie upuścić klucz podstawowy i ponownie dodać autoinkrementację

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

następnie dodaj z powrotem automatyczną inkrementację

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

następnie ustaw automatyczną inkrementację z powrotem do poprzedniej wartości

ALTER TABLE `xx` AUTO_INCREMENT = 5;

2

Możesz również użyć IGNOREsłowa kluczowego, na przykład:

 update IGNORE table set primary_field = 'value'...............
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.