web-dev-qa-db-fra.com

Incrémentation automatique après suppression dans MySQL

J'ai une table MySQL avec un champ de clé primaire qui a AUTO_INCREMENT sur . Après avoir lu d'autres articles ici, j'ai remarqué des personnes avec le même problème et des réponses variées. Certains recommandent de ne pas utiliser cette fonctionnalité, d'autres indiquent qu'elle ne peut pas être "corrigée".

J'ai:

table: course
fields: courseID, courseName

Exemple: nombre d'enregistrements dans la table: 18. Si je supprime les enregistrements 16, 17 et 18, je suppose que l'enregistrement suivant aura l'ID de parcours de 16, mais sera 19 parce que le dernier ID de cours entré était 18.

Mes connaissances en SQL ne sont pas étonnantes, mais y a-t-il un moyen d'actualiser ou de mettre à jour ce nombre avec une requête (ou un paramètre dans l'interface phpMyAdmin)?

Cette table se rapportera aux autres dans une base de données.


Compte tenu de tous les conseils, j'ai décidé d'ignorer ce "problème". Je vais simplement supprimer et ajouter des enregistrements tout en laissant l'incrémentation automatique faire son travail. J'imagine que le numéro n'a pas d'importance, puisqu'il est uniquement utilisé comme identifiant unique et qu'il n'a pas (comme mentionné ci-dessus) business meaning.

Pour ceux que j’ai peut-être confondus avec mon message original: Je ne souhaite pas utiliser ce champ pour connaître le nombre d’enregistrements que j’ai. Je voulais juste que la base de données soit soignée et un peu plus cohérente.

60
OmidTahouri

Ce que vous essayez de faire semble dangereux, car ce n’est pas l’utilisation prévue de AUTO_INCREMENT.

Si vous voulez vraiment trouver la plus petite valeur de clé inutilisée, n'utilisez pas du tout AUTO_INCREMENT et gérez vos clés manuellement. Cependant, ce n'est pas une pratique recommandée.

Faites un pas en arrière et demandez "pourquoi devez-vous recycler les valeurs de clé?" Est-ce que la valeur non signée INT (ou BIGINT) ne fournit pas assez de place pour la clé? 

Allez-vous vraiment avoir plus de 18,446,744,073,709,551,615 enregistrements uniques au cours de la vie de votre application?

66
Dolph
ALTER TABLE foo AUTO_INCREMENT=1

Si vous avez supprimé les entrées les plus récentes, cela devrait permettre d’utiliser celle qui est disponible la plus basse. En tant que, dans la mesure où il n'y a pas déjà 19, supprimer 16-18 réinitialisera l'autocrémentation pour utiliser 16.


EDIT: J'ai raté le sujet sur phpmyadmin. Vous pouvez également le définir ici. Accédez à l'écran du tableau, puis cliquez sur l'onglet Opérations. Il existe un champ AUTOINCREMENT que vous pouvez définir manuellement sur ce dont vous avez besoin.

33
monksp

Les clés d'auto-incrémentation primaires dans la base de données sont utilisées pour identifier de manière unique une ligne donnée et ne doivent recevoir aucune signification business . Donc, laissez la clé primaire en l’état et ajoutez une autre colonne appelée par exemple courseOrder. Ensuite, lorsque vous supprimez un enregistrement de la base de données, vous pouvez envoyer une instruction UPDATE supplémentaire afin de décrémenter la colonne courseOrder de toutes les lignes dont la valeur courseOrder est supérieure à celle que vous supprimez actuellement.

En remarque, vous ne devez jamais modifier la valeur d'une clé primaire dans une base de données relationnelle, car d'autres tables pourraient la référencer en tant que clé étrangère et la modifier pourrait violer les contraintes référentielles.

16
Darin Dimitrov

Essayez:

SET @num: = 0;

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

ALTER TABLE tableName AUTO_INCREMENT = 1;

Cela réinitialisera la valeur auto-incrémentée, puis comptera chaque ligne pendant la création d'une nouvelle valeur.

exemple: avant

  • 1: première valeur ici
  • 2: deuxième valeur ici
  • X: valeur supprimée
  • 4: le reste de la table
  • 5: Le reste du reste ..

la table affichera donc le tableau: 1,2,4,5

Exemple: APRES (si vous utilisez cette commande, vous obtiendrez)

  • 1: première valeur ici
  • 2: deuxième valeur ici
  • 3: le reste de la table
  • 4: le reste du reste

Aucune trace de la valeur supprimée et le reste de l'incrémenté continue avec ce nouveau compte.

MAIS

  1. Si quelque chose sur votre code utilise quelque chose la valeur auto-incrémentée ... peut-être que cette attribution posera problème.
  2. Si vous n'utilisez pas cette valeur dans votre code, tout devrait bien se passer.
8
Claod

Vous ne devriez pas vous fier à l'identifiant AUTO_INCREMENT pour vous dire combien d'enregistrements vous avez dans la table. Vous devriez utiliser SELECT COUNT(*) FROM course. Les identifiants servent à identifier le cours de manière unique et peuvent être utilisés comme références dans d'autres tables. Par conséquent, vous ne devez pas répéter les identifiants ni chercher à réinitialiser le champ d'incrémentation automatique.

3
Mike Sherov

vous pouvez sélectionner les identifiants comme ceci:

set @rank = 0;
select id, @rank:=@rank+1 from tbl order by id

le résultat est une liste d'identifiants et leurs positions dans la séquence.

vous pouvez aussi réinitialiser les identifiants comme ceci:

set @rank = 0;
update tbl a join (select id, @rank:=@rank+1 as rank from tbl order by id) b
  on a.id = b.id set a.id = b.rank;

vous pouvez aussi simplement imprimer le premier identifiant inutilisé comme ceci:

select min(id) as next_id from ((select a.id from (select 1 as id) a
  left join tbl b on a.id = b.id where b.id is null) union
  (select min(a.id) + 1 as id from tbl a left join tbl b on a.id+1 = b.id
  where b.id is null)) c;

après chaque insertion, vous pouvez réinitialiser l'auto_increment:

alter table tbl auto_increment = 16

ou explicitement définir la valeur id lors de l'insertion:

insert into tbl values (16, 'something');

ce n'est généralement pas nécessaire, vous avez count(*) et la possibilité de créer un numéro de classement dans vos jeux de résultats. un classement typique pourrait être:

set @rank = 0;
select a.name, a.amount, b.rank from cust a,
  (select amount, @rank:=@rank+1 as rank from cust order by amount desc) b
  where a.amount = b.amount

clients classés par montant dépensé.

2
user262976

Je suis venu ici pour chercher une réponse à la question sur le titre "MySQL - Auto Increment after delete", mais je n'ai pu trouver de réponse à cette question que dans les questions.

En utilisant quelque chose comme:

DELETE FROM table;
ALTER TABLE table AUTO_INCREMENT = 1;

Notez que la réponse de Darin Dimitrov explique très bien AUTO_INCREMENT et son utilisation. Jetez un oeil là-bas avant de faire quelque chose que vous pourriez regretter.

PS: La question elle-même est plus "Why you need to recycle key values?" et la réponse de Dolph couvre ça.

2
Michel Ayres

J'ai eu une méthode très simple mais délicate. 

Lors de la suppression d'une ligne, vous pouvez conserver les ID dans une autre table temporaire. Après cela, lorsque vous insérerez de nouvelles données dans la table principale, vous pourrez rechercher et sélectionner les identifiants de la table temporaire. Alors utilisez une vérification ici. Si la table temporaire n'a pas d'identifiant, calculez l'identifiant maximum dans la table principale et définissez le nouvel identifiant comme suit: new_ID = old_max_ID+1.

NB: Vous ne pouvez pas utiliser la fonctionnalité d’incrémentation automatique ici.

1
arefin2k

Je peux penser à de nombreux scénarios dans lesquels vous pourriez avoir besoin de le faire, en particulier pendant un processus de migration ou de développement. Par exemple, je venais tout juste de créer une nouvelle table en joignant deux tables existantes (dans le cadre d'un processus d'installation complexe), puis je devais ajouter une clé primaire après l'événement. Vous pouvez supprimer la colonne de clé primaire existante, puis procédez ainsi.

ALTER TABLE my_table ADD `ID` INT NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`ID`);

Pour un système actif, ce n'est pas une bonne idée, surtout s'il y a d'autres tables avec des clés étrangères pointant vers elle.

1
Peter Smartt

Il existe en fait un moyen de résoudre ce problème. Vous supprimez d’abord la colonne de clé primaire auto_incremented, puis vous l’ajoutez à nouveau, comme ceci:

ALTER TABLE table_name DROP column_name;
ALTER TABLE table_name ADD column_name int not null auto_increment primary key first;
1
Geni Jaho

Vous pouvez utiliser votre logiciel/script client mysql pour spécifier le point de départ de la clé primaire après la suppression des enregistrements requis.

0
Sarfraz

Vous pouvez penser à créer un déclencheur après la suppression afin de pouvoir mettre à jour la valeur de l'auto-incrémentation et la valeur de l'ID de toutes les lignes qui ne ressemble pas à ce que vous vouliez voir.

Ainsi, vous pouvez travailler avec la même table et l'incrémentation automatique sera automatiquement corrigée chaque fois que vous supprimez une ligne, le déclencheur la corrigera.

0
Aloui Khalil

Ce n'est vraiment pas à recommander. Si vous avez une base de données volumineuse avec plusieurs tables, vous avez probablement déjà enregistré un ID utilisateur en tant qu'id dans la table 2. Si vous réorganisez la table 1, il est probable que l'ID utilisateur souhaité ne sera pas l'ID de la table 2 souhaité.

0
Joshua Omwoyo

voici une fonction qui résout votre problème

    public static void fixID(Connection conn, String table) {

    try {
        Statement myStmt = conn.createStatement();
        ResultSet myRs;
        int i = 1, id = 1, n = 0;
        boolean b;
        String sql;

        myRs = myStmt.executeQuery("select max(id) from " + table);
        if (myRs.next()) {
            n = myRs.getInt(1);
        }
        while (i <= n) {
            b = false;
            myRs = null;
            while (!b) {
                myRs = myStmt.executeQuery("select id from " + table + " where id=" + id);
                if (!myRs.next()) {
                    id++;
                } else {
                    b = true;
                }
            }

            sql = "UPDATE " + table + " set id =" + i + " WHERE id=" + id;
            myStmt.execute(sql);
            i++;
            id++;
        }

    } catch (SQLException e) {
        e.printStackTrace();
    }
}
0
dani bilel
if($id == 1){ // deleting first row
            mysqli_query($db,"UPDATE employees  SET id=id-1 WHERE id>1");
        }
        else if($id>1 && $id<$num){ // deleting middle row
            mysqli_query($db,"UPDATE employees  SET id=id-1 WHERE id>$id");
        }
        else if($id == $num){ // deleting last row
            mysqli_query($db,"ALTER TABLE employees AUTO_INCREMENT = $num");
        }
        else{
            echo "ERROR";
        }

        mysqli_query($db,"ALTER TABLE employees AUTO_INCREMENT = $num");
0
Vaso Nadiradze

Ce que vous essayez de faire est très dangereux. Pensez-y bien. Il y a une très bonne raison pour le comportement par défaut de l'incrémentation automatique. 

Considère ceci:

Un enregistrement est supprimé dans une table ayant une relation avec une autre table. L'enregistrement correspondant dans la deuxième table ne peut pas être supprimé pour des raisons d'audit. Cet enregistrement devient orphelin à partir de la première table. Si un nouvel enregistrement est inséré dans la première table et qu'une clé primaire séquentielle est utilisée, cet enregistrement est maintenant lié à l'orphelin. Évidemment, c'est mauvais. En utilisant une PK incrémentée automatiquement, un identifiant qui n'a jamais été utilisé auparavant est toujours garanti. Cela signifie que les orphelins restent des orphelins, ce qui est correct. 

0
Charles Robertson