Оновлення первинного ключа 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,

5
наступного разу додайте унікальний ключ із тими ж стовпцями, що і первинний ключ, а потім оновіть первинний ключ
knittl

1
@Ignacio, це живе на сервері, але це сервер резервного копіювання :-). Я не DBA, але я не буду пробувати це на
реально

1
@knittl, так, це я думав зараз, хоч дуже пізно :-)
simplfuzz

4
@pixeline: це складний первинний ключ.
Ігнасіо Васкес-Абрамс

Відповіді:


231

Наступного разу використовуйте одну заяву "змінити таблицю" для оновлення первинного ключа.

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'...............
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.