web-dev-qa-db-fra.com

Mise à jour de la clé primaire MySQL

J'ai une table user_interactions avec 4 colonnes:

 user_1
 user_2
 type
 timestamp

La clé primaire est (user_1,user_2,type)
et je veux passer à (user_2,user_1,type)

Alors ce que j'ai fait était:

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

et le tour est joué ...

Le problème est que la base de données est en direct sur un serveur.

Ainsi, avant que je puisse mettre à jour la clé primaire, de nombreux doublons se sont déjà glissés et continuent de s’infiltrer.

Que faire?

Ce que je veux faire maintenant est de supprimer les doublons et de conserver ceux avec le dernier timestamp (qui est une colonne dans la table).

Et puis en quelque sorte mettre à jour la clé primaire à nouveau.

87
dharm0us

La prochaine fois, utilisez une seule instruction "alter table" pour mettre à jour la clé primaire.

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

Pour réparer les choses:

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;

Le verrou devrait empêcher d’autres mises à jour d’arriver pendant que vous le faites. Le temps que cela prend dépend évidemment de la taille de votre table.

Le problème principal est si vous avez des doublons avec le même horodatage.

200
Martin

S'il s'avère que la clé primaire est une valeur auto_increment, vous devez supprimer l'incrément automatique, puis supprimer la clé primaire, puis rajouter l'incrément automatique.

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

puis rajouter l'incrément automatique

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

puis réglez l'incrément automatique à la valeur précédente

ALTER TABLE `xx` AUTO_INCREMENT = 5;
10
frazras

Vous pouvez également utiliser le mot clé IGNORE, par exemple:

 update IGNORE table set primary_field = 'value'...............
2
Sarfraz