Cập nhật khóa chính MySQL


103

Tôi có một bảng user_interactionsvới 4 cột:

 user_1
 user_2
 type
 timestamp

Khóa chính là (user_1,user_2,type)
và tôi muốn thay đổi thành(user_2,user_1,type)

Vì vậy, những gì tôi đã làm là:

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

và Voila...

Vấn đề là cơ sở dữ liệu đang tồn tại trên một máy chủ.

Vì vậy, trước khi tôi có thể cập nhật khóa chính, nhiều bản sao đã len lỏi vào và chúng liên tục len lỏi vào.

Để làm gì?

Những gì tôi muốn làm bây giờ là loại bỏ các bản sao và giữ lại những bản mới nhất timestamp(là một cột trong bảng).

Và sau đó bằng cách nào đó cập nhật lại khóa chính.


16
Tôi đột nhiên cảm thấy xấu cho mỗi DBA duy nhất tôi nguyền rủa dưới hơi thở của tôi ...
Ignacio Vazquez-Abrams

5
lần sau thêm một khóa duy nhất với các cột tương tự như khóa chính, sau đó cập nhật khóa chính
knittl

1
@Ignacio, nó hoạt động trên một máy chủ, nhưng đó là một máy chủ backup-backup :-). Tôi không phải là DBA, nhưng tôi sẽ không thử điều này trên một máy chủ thực sự đang hoạt động :-)
simplfuzz 26/02/10

1
@knittl, vâng đó là những gì tôi nghĩ bây giờ, mặc dù rất muộn :-)
simplfuzz

4
@pixeline: Đó là một khóa chính phức hợp.
Ignacio Vazquez-Abrams

Câu trả lời:


231

Lần tới, hãy sử dụng một câu lệnh "bảng thay thế" để cập nhật khóa chính.

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

Để khắc phục sự cố:

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;

Khóa sẽ ngừng cập nhật thêm trong khi bạn đang thực hiện việc này. Điều này mất bao lâu rõ ràng phụ thuộc vào kích thước của bàn của bạn.

Vấn đề chính là nếu bạn có một số bản sao có cùng dấu thời gian.


11

Nếu khóa chính là giá trị auto_increment, bạn phải xóa số tự động tăng, sau đó thả khóa chính rồi thêm lại số tự động tăng

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

sau đó thêm lại mức tăng tự động

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

sau đó đặt tăng tự động trở lại giá trị trước đó

ALTER TABLE `xx` AUTO_INCREMENT = 5;

2

Bạn cũng có thể sử dụng IGNOREtừ khóa, ví dụ:

 update IGNORE table set primary_field = 'value'...............
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.