57 votes

Trouver le prochain identifiant disponible dans MySQL

Je dois trouver le prochain identifiant disponible (s'il y a 5 données dans la base, je dois trouver le prochain emplacement d'insertion disponible qui est 6) dans une base de données MySQL. Comment puis-je faire cela ? J'ai utilisé MAX(id) Mais lorsque je supprime certaines lignes de la base de données, l'ancienne valeur maximale qui n'a pas été mise à jour est conservée.

0 votes

Donc ce que vous demandez, c'est de trouver le premier identifiant disponible. Si vous en avez 5, mais que vous supprimez le troisième, alors l'identifiant 3 devrait être disponible pour insérer une nouvelle ligne ?

4 votes

C'est un mauvais conseil... la plupart des bases de données incrémentent simplement par une clé synthétique. Elles n'essaient pas de réutiliser les anciennes valeurs. Elles incrémentent simplement.

0 votes

Burak : voulez-vous trouver le "prochain identifiant disponible" (qui est max(id) + 1), ou le "prochain identifiant jamais utilisé" ?

90voto

Eimantas Points 29052

Mise à jour 2014-12-05

Je ne recommande pas cette approche pour les raisons exposées dans la réponse (acceptée) de Simon ainsi que dans le commentaire de Diego. Veuillez utiliser la requête ci-dessous à vos propres risques.


Réponse originale

Le plus court que j'ai trouvé sur le site du développeur MySQL :

SELECT Auto_increment
FROM information_schema.tables
WHERE table_name='the_table_you_want'

Attention, si vous avez plusieurs bases de données avec les mêmes tables, vous devez également spécifier le nom de la base de données, comme ceci :

SELECT Auto_increment
FROM information_schema.tables
WHERE table_name = 'the_table_you_want'
      AND table_schema = 'the_database_you_want';

16 votes

Sympa, mais n'oubliez pas ! D'autres utilisateurs de la base de données peuvent insérer un enregistrement juste après que vous ayez effectué cette requête et avant que vous n'insériez réellement l'enregistrement. Cela fonctionne bien dans certains cas, mais gardez-le à l'esprit !

1 votes

J'ai essayé cela, et auto_increment m'a renvoyé null. La table dans laquelle je fais ma sélection contient 5 enregistrements, un champ appelé id qui est la clé primaire. Quelqu'un peut-il me dire pourquoi c'est le cas ?

0 votes

@LeoKing - La colonne doit être une colonne à incrémentation automatique pour récupérer la valeur.

24voto

Simon Groenewolt Points 7046

Je ne pense pas que l'on puisse être sûr de l'existence de la suivant car quelqu'un pourrait insérer une nouvelle ligne juste après que vous ayez demandé l'identifiant suivant. Vous auriez au moins besoin d'une transaction et, si je ne me trompe pas, vous ne pouvez obtenir que l'identifiant utilisé. après l'insérer, du moins c'est la façon courante de le faire -- voir http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html

0 votes

Je suis d'accord avec ce commentaire. Pour l'intégrité des données, je générerais et utiliserais toujours un nouveau numéro. Si vous voulez utiliser les identifiants "inutilisés", je vous recommande de créer un fichier php sur une tâche cron qui est exécuté lorsqu'il n'y a sûrement pas d'utilisateurs dans votre application web et vous "réduisez" vos lignes aux identifiants inutilisés. Vous devez vous assurer de mettre à jour toutes les autres tables qui font référence à celle-ci, et de les mettre à jour en conséquence.

11 votes

@Oliver M Grech : "sûrement pas d'utilisateurs dans votre webapp" - cela n'existe pas, l'Internet n'a pas d'heures de travail. Selon "oh, il est 2 heures du matin en GMT+1, donc pas d'utilisateurs". sera reviennent et vous mordent (je suis passé par là, je l'ai fait).

22voto

Jarry Points 131

En complément de la réponse de Lukasz Lysik - le type de SQL LEFT-JOIN.
Si je comprends bien, si on a les identifiants : 1,2,4,5, il devrait retourner 3.

SELECT u.Id + 1 AS FirstAvailableId
FROM users u
LEFT JOIN users u1 ON u1.Id = u.Id + 1
WHERE u1.Id IS NULL
ORDER BY u.Id
LIMIT 0, 1

J'espère que cela aidera certains visiteurs, même si les messages sont plutôt anciens.

0 votes

De même, au lieu de la limite et de l'ordre par, vous pouvez utiliser min(u.id)+1. Je ne suis pas sûr de savoir quelle méthode est la plus rapide - probablement la vôtre.

0 votes

Pour accélérer considérablement cette opération, vous devez ajouter un group by. "group by u1.id order by u1.id limit 1".

12voto

nickf Points 185423

Vu ce que vous avez dit dans un commentaire :

J'ai besoin de récupérer l'identifiant et de le convertir dans une autre base, donc je dois récupérer l'identifiant suivant avant l'insertion car le code converti sera inséré aussi.

Il y a un moyen de faire ce que vous demandez, qui est de demander à la table ce que la l'identifiant de la prochaine ligne insérée sera être avant de l'insérer :

SHOW TABLE STATUS WHERE name = "myTable"

il y aura un champ dans cet ensemble de résultats appelé "Auto_increment" qui vous indique la prochaine valeur d'auto-incrément.

11voto

Lukasz Lysik Points 5679

Si je comprends bien, si on a des identifiants : 1,2,4,5, il devrait retourner 3.

SELECT t1.id + 1
FROM theTable t1
WHERE NOT EXISTS (
    SELECT * 
    FROM theTable t2
    WHERE t2.id = t1.id + 1
)
LIMIT 1

0 votes

Pour info, il y a un problème avec ce code : S'il n'y a pas encore de lignes dans le tableau, il ne retournera rien.

0 votes

S'il y a des lignes dans le tableau, est-ce sûr ? Certaines des autres réponses suggèrent d'utiliser uniquement des ID frais, mais ce serait formidable si nous pouvions utiliser cela et avoir une intégrité des données.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X