MySQL birincil anahtarını güncelleme


104

Ben bir tablo var user_interactions4 sütunlu:

 user_1
 user_2
 type
 timestamp

Birincil anahtar (user_1,user_2,type)
ve şu şekilde değiştirmek istiyorum:(user_2,user_1,type)

Yani yaptığım şey şuydu:

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

ve voila ...

Sorun, veritabanının bir sunucuda canlı olmasıdır.

Bu yüzden, birincil anahtarı güncellemeden önce, birçok kopya çoktan içeri girdi ve sürekli olarak içeri giriyorlar.

Ne yapalım?

Şimdi yapmak istediğim, kopyaları kaldırmak ve en son olanları saklamak timestamp (tablodaki bir sütun) .

Ve sonra bir şekilde birincil anahtarı tekrar güncelleyin.


16
Nefesimin altında lanetlediğim her DBA için birdenbire üzülüyorum ...
Ignacio Vazquez-Abrams

5
bir dahaki sefere birincil anahtarla aynı sütunlara sahip benzersiz bir anahtar ekleyin, ardından birincil anahtarı güncelleyin
knittl

1
@Ignacio, bir sunucuda yayında, ancak bu bir yedekleme-yedekleme sunucusudur :-). Ben bir DBA değilim, ancak bunu GERÇEKTEN canlı bir sunucuda
denemeyeceğim

1
@knittl, evet şimdi düşündüğüm buydu, ama çok geç :-)
simplfuzz

4
@pixeline: Bu bir bileşik birincil anahtardır.
Ignacio Vazquez-Abrams

Yanıtlar:


233

Bir dahaki sefere, birincil anahtarı güncellemek için tek bir "tabloyu değiştir" ifadesi kullanın.

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

Bir şeyleri düzeltmek için:

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;

Kilit, bunu yaparken gelecek güncellemeleri durdurmalıdır. Bunun ne kadar süreceği tabii ki masanızın boyutuna bağlıdır.

Ana sorun, aynı zaman damgasına sahip bazı kopyalarınız varsa.


11

Birincil anahtar bir auto_increment değeri olursa, otomatik artışı kaldırmanız, ardından birincil anahtarı bırakmanız ve ardından otomatik artırmayı yeniden eklemeniz gerekir.

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

sonra otomatik artışı tekrar ekleyin

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

ardından otomatik artışı önceki değere geri ayarlayın

ALTER TABLE `xx` AUTO_INCREMENT = 5;

2

IGNOREAnahtar kelimeyi de kullanabilirsiniz , örneğin:

 update IGNORE table set primary_field = 'value'...............
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.