web-dev-qa-db-fra.com

Réorganiser / réinitialiser la clé primaire à incrémentation automatique

J'ai une table MySQL avec une clé primaire à incrémentation automatique. J'ai supprimé des lignes au milieu de la table. Maintenant, j'ai, par exemple, quelque chose comme ceci dans la colonne ID: 12, 13, 14, 19, 20. J'ai supprimé les lignes 15, 16, 17 et 18.

Je souhaite réaffecter/réinitialiser/réorganiser la clé primaire afin d’avoir une continuité, c’est-à-dire faire passer le 19 à 15, le 20 à 16, etc.

Comment puis-je le faire?

118
Jonathan

Vous pouvez supprimer la colonne de clé primaire et la recréer. Tous les identifiants doivent ensuite être réaffectés dans l'ordre.

Cependant, c'est probablement une mauvaise idée dans la plupart des situations. Si vous avez d'autres tables qui ont des clés étrangères à cette table, cela ne fonctionnera certainement pas.

86
Tom Haigh

Même si cette question semble être assez ancienne, nous publierons une réponse pour quelqu'un qui cherche ici.

SET @count = 0;
UPDATE `users` SET `users`.`id` = @count:= @count + 1;

Si la colonne est utilisée comme clé étrangère dans d'autres tables, veillez à utiliser ON UPDATE CASCADE Au lieu de la valeur par défaut ON UPDATE NO ACTION Pour la relation de clé étrangère dans ces tables.

De plus, afin de réinitialiser le nombre AUTO_INCREMENT, Vous pouvez immédiatement émettre l'instruction suivante.

ALTER TABLE `users` AUTO_INCREMENT = 1;

Pour MySQL, il réinitialisera la valeur à MAX(id) + 1.

335
Anshul

Pour réinitialiser les identifiants de ma table utilisateur, j'utilise la requête SQL suivante. Il a été dit plus haut que cela détruirait toutes les relations que vous pourriez avoir avec d’autres tables.

ALTER TABLE `users` DROP `id`;
ALTER TABLE `users` AUTO_INCREMENT = 1;
ALTER TABLE `users` ADD `id` int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;
54
Ryan

Vous pouvez simplement utiliser cette requête

alter table abc auto_increment = 1;
30
user188226
SET  @num := 0;

UPDATE your_table SET id = @num := (@num+1);

ALTER TABLE your_table AUTO_INCREMENT =1;

Je pense que ça va le faire

14
bagyei37

Ou, dans PhpMyAdmin, supprimez l'indicateur "AutoIncrement", sauvegardez-le, réglez-le à nouveau et enregistrez.Cela le réinitialise.

13
lbrutti

dans phpmyadmin

remarque: cela fonctionnera si vous supprimez les dernières lignes et non les lignes du milieu.

allez à votre table-> cliquez sur le menu des opérations-> allez sur les options de la table-> changez AUTO_INCREMENT en ce no où vous voulez commencer.

votre auto-incrémentation de table part de ce non.

l'essayer enter image description here

1
Anjani Barnwal
SELECT * from `user` ORDER BY `user_id`; 

SET @count = 0;

UPDATE `user`  SET `user_id` = @count:= @count + 1;

ALTER TABLE `user_id` AUTO_INCREMENT = 1;

si tu veux order by

1
Shubham Malik

pour InnoDB, faites ceci (cela supprimera tous les enregistrements d'une table, faites d'abord une sauvegarde):

SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS ;
SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION ;
SET NAMES utf8 ;
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 ;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 ;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' ;
SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 ;
/* ================================================= */

drop table tablename;
CREATE TABLE `tablename` (
   table structure here!

) ENGINE=InnoDB AUTO_INCREMENT=  ai number to reset  DEFAULT CHARSET= char set here;



/* ================================================= */
SET SQL_MODE=@OLD_SQL_MODE ;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS ;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS ;
SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT ;
SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS ;
SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION ;
SET SQL_NOTES=@OLD_SQL_NOTES ;
0
Luis

Vous pouvez supprimer la fonctionnalité d'incrémentation automatique de la clé primaire de cette colonne, puis chaque fois que vous mettez à jour cette colonne, lancez une requête préalable qui comptera toutes les lignes de la table, puis exécutera une boucle qui itérera à travers ce nombre de lignes en insérant chaque valeur dans la colonne. ligne correspondante, puis exécutez une requête en insérant une nouvelle ligne dont la valeur correspond au nombre total de lignes plus un. Cela fonctionnera parfaitement et constitue la solution la plus absolue à quelqu'un qui tente d'accomplir ce que vous êtes. Voici un exemple de code que vous pouvez utiliser pour la fonction:

$table_row_count = mysql_result(mysql_query("SELECT COUNT(`field_1`) FROM `table`"), 0);
$viewsrowsdata = mysql_query("
    SELECT `rank`, `field1`, `field2`, `field3`, `field4`
        FROM (SELECT (@rank:=@rank+1) as `rank`, `field1`, `field2`, `field3`, `field4`
            FROM (SELECT * FROM `views`) a
            CROSS JOIN (SELECT @rank:=0) b
            ORDER BY rank ASC) c
");
while ($row = mysql_fetch_assoc($viewsrowsdata)) {
    $data[] = $row;
}
foreach ($data as $row) {
    $new_field_1 = (int)$row['rank'];
    $old_field_1 = (int)$row['field1'];
    mysql_query("UPDATE `table` SET `field_1` = $new_field_1 WHERE `field_1` = $old_field_1");
}
mysql_query("INSERT INTO `table` (`field1`, `field2`, `field3`, `field4`) VALUES ('$table_row_count' + 1, '$field_2_value', 'field_3_value', 'field_4_value')");

Ici, j'ai créé un tableau associatif que j'avais ajouté à une colonne de rang avec la requête dans une requête select, qui donnait à chaque ligne une valeur de rang commençant à 1. J'ai ensuite itéré à travers le tableau associatif.

Une autre option aurait été d'obtenir le nombre de lignes, d'exécuter une requête de sélection de base, d'obtenir le tableau associatif et de l'itérer de la même manière, mais avec une variable ajoutée qui se met à jour à chaque itération. Ceci est moins flexible mais accomplira la même chose.

$table_row_count = mysql_result(mysql_query("SELECT COUNT(`field_1`) FROM `table`"), 0);
$viewsrowsdata = mysql_query("SELECT * FROM `table`");
$updated_key = 0;
while ($row = mysql_fetch_assoc($viewsrowsdata)) {
    $data[] = $row;
}
foreach ($data as $row) {
    $updated_key = $updated_key + 1;
    mysql_query("UPDATE `table` SET `field_1` = '$updated_key' WHERE `field_1` = '$row['field_1']'");
}
mysql_query("INSERT INTO `table` (`field1`, `field2`, `field3`, `field4`) VALUES ('$table_row_count' + 1, '$field_2_value', 'field_3_value', 'field_4_value')");
0
willy

Mon avis est de créer une nouvelle colonne appelée row_order. puis réorganisez cette colonne. Je n'accepte pas les modifications apportées à la clé primaire. À titre d’exemple, si la colonne de commande est banner_position, j’ai fait quelque chose comme ceci: c’est pour supprimer, mettre à jour, créer une colonne de position de bannière. Appelez cette fonction pour les réorganiser.

public function updatePositions(){
    $offers = Offer::select('banner_position')->orderBy('banner_position')->get();
    $offersCount = Offer::max('banner_position');
    $range = range(1, $offersCount);

    $existingBannerPositions = [];
    foreach($offers as $offer){
        $existingBannerPositions[] = $offer->banner_position;
    }
    sort($existingBannerPositions);
    foreach($existingBannerPositions as $key => $position){
        $numbersLessThanPosition = range(1,$position);
        $freshNumbersLessThanPosition = array_diff($numbersLessThanPosition, $existingBannerPositions);
        if(count($freshNumbersLessThanPosition)>0) {
            $existingBannerPositions[$key] = current($freshNumbersLessThanPosition);
            Offer::where('banner_position',$position)->update(array('banner_position'=> current($freshNumbersLessThanPosition)));
        }
    }
}
0
Sameera

J'avais les mêmes doutes, mais je ne pouvais apporter aucun changement à la table. J'ai décidé de procéder comme suit, vu que mon identifiant ne dépassait pas le nombre maximum défini dans la variable @count:

SET @count = 40000000;
UPDATE `users` SET `users`.`id` = @count:= @count + 1;

SET @count = 0;
UPDATE `users` SET `users`.`id` = @count:= @count + 1;

ALTER TABLE `users` AUTO_INCREMENT = 1;

La solution prend, mais elle est sûre et nécessaire car ma table possédait des clés étrangères avec des données dans une autre table.

0
Rodrigo Prazim

Cela fonctionne - https://stackoverflow.com/a/5437720/10219008.....but si vous rencontrez un problème 'Code d'erreur: 1265. Données tronquées pour la colonne' id 'à la ligne 1 '... Puis lancez ce qui suit. Ajout de ignorer sur la requête de mise à jour.

SET @count = 0;
set sql_mode = 'STRICT_ALL_TABLES';
UPDATE IGNORE web_keyword SET id = @count := (@count+1);
0
Anush B M

Le meilleur choix consiste à modifier la colonne et à supprimer l'attribut auto_increment. Emettez ensuite une autre instruction alter et remettez auto_increment dans la colonne. Ceci réinitialisera le nombre au maximum + 1 des lignes actuelles et préservera ainsi les références de clé étrangère à cette table, à partir d'autres tables de votre base de données, ou à toute autre utilisation de clé pour cette colonne.

0
Grwww