Question

Bonjour, j’ai besoin de générer des numéros de compte uniques à 9 chiffres. Voici mon pseudocode:

function generateAccNo()

    generate an account number between 100,000,000 and 999,999,999

    if the account number already exists in the DB 
        call generateAccNo()    /* recursive call */
    else
        return new accout number
    end if

end function

La fonction semble bien fonctionner, mais je suis un peu inquiète pour l'appel récursif.

Est-ce que cela provoquera des fuites de mémoire (PHP 5 sous Apache)?

Est-ce un moyen acceptable de résoudre ce problème?

Merci pour votre contribution.

Était-ce utile?

La solution

Vous réalisez que cela pourrait très bien causer un débordement de pile, non? À mesure que le nombre de clients augmente, la probabilité de ne pas trouver un numéro de compte acceptable augmente.

Aussi, pourquoi ne pouvez-vous pas simplement créer des numéros de compte séquentiels et simplement augmenter d'un numéro à chaque fois? Avec cette approche, il vous suffirait de lire le nombre maximal d’ID actuellement dans la base de données et de l’incrémenter.

Désolé d'être aussi direct, mais votre solution est un moyen terrible de résoudre le problème. Il utilisera des tonnes de mémoire (car la pile s'agrandit éventuellement à l'infini) et fera des tonnes d'appels coûteux à la base de données.

Vous devriez vraiment envisager une autre approche:
Je recommande fortement d’incrémenter le numéro de client chaque fois que vous créez un client. En fait, si vous configurez votre base de données correctement (avec l'incrémentation automatique sur la colonne id), vous n'aurez même pas à définir l'id. L'identifiant sera défini pour vous chaque fois que vous insérez un nouveau client.

Autres conseils

Je ne pense vraiment pas que cela se résume à la récursivité par opposition à la mise en boucle: les deux sont sujets à des problèmes lorsque le jeu de données se développe et si la génération de nombres aléatoires n’est pas correctement implémentée. Deux idées me viennent à l’esprit:

. GUID

Si un identifiant vraiment unique est requis avec le moins d'effort possible, considérez un GUID, votre base de données sera probablement en mesure de vous l'affecter lors de l'insertion, sinon d'en créer un dans le code. Il est garanti d'être unique bien que ce ne soit pas très convivial. Cependant, en combinaison avec un AccountRecordId séquentiel généré par la base de données lors de l'insertion, vous obtiendrez une combinaison solide

. Clé composite: aléatoire + séquentielle

Une façon de répondre à tous les besoins, même si, au premier abord, cela semble un peu compliqué, est de créer un numéro de compte composite à partir d’une clé séquentielle de 5 chiffres (ou plus), puis de 5 autres chiffres aléatoires. Si le numéro aléatoire était dupliqué, cela n'aurait pas d'importance, car l'identifiant séquentiel garantirait l'unicité du numéro de compte complet

Il n'est pas nécessaire d'utiliser un appel récursif ici. Exécutez une boucle while simple dans la fonction testant la non-existence en tant que conditionnel, par exemple

.
function generateAccNo()

    generate an account number between 100,000,000 and 999,999,999

    while ( the account number already exists in the DB ) {
         generate new account number;
    }
    return new account number

end function

Générer et tester au hasard est une approche sous-optimale pour générer des numéros de compte uniques, bien que, si ce code est destiné à autre chose qu'un jouet.

Cela semble aller bien, mais je pense que vous avez besoin d’une sorte de condition de dé, combien de fois allez-vous la laisser courir avant d’abandonner?

Je sais que cela semble improbable avec la gamme de numéros énormes, mais il se peut que quelque chose qui ne va pas vous ramène à l'appel précédent, qui s'appellera à nouveau ad-nauseum.

La génération séquentielle des numéros de compte est un risque pour la sécurité. Vous devriez trouver un autre algorithme pour le faire.

Vous pouvez également gérer une table séparée contenant un tampon de numéros de compte générés et connus. Cette table doit avoir un identifiant entier auto-incrémenté. Lorsque vous voulez un numéro de compte, extrayez simplement l'enregistrement avec l'indice le plus bas dans la mémoire tampon et supprimez-le de cette table. Utilisez un processus qui exécute régulièrement qui reconstitue la mémoire tampon et s’assure qu’il a la capacité > > utilisation normale. L’avantage est que le temps passé par l’utilisateur final à créer un numéro de compte sera essentiellement constant.

De plus, il convient de noter que le temps de traitement ou les risques de récurrence ou d’itération constituent le véritable problème, c’est le déterminisme et le temps de traitement de requêtes répétées dans la base de données. J'aime la solution TheZenker de random + séquentielle. Garanti de générer un identifiant unique sans ajouter de surcharge inutile.

Vous n'avez pas besoin d'utiliser la récursion ici. Une simple boucle serait tout aussi rapide et consommerait moins d’espace de pile.

Vous pouvez le mettre dans une boucle while:

function generateAccNo()

    while (true) {    

      generate an account number between 100,000,000 and 999,999,999

      if the account number already exists in the DB 
          /* do nothing */
      else
          return new accout number
      end if
    }

end function

Pourquoi pas:

lock_db
do
    account_num <= generate number
while account_num in db

put row with account_num in db

unlock_db

Pourquoi ne pas laisser la base de données gérer cela? Dans SQL Server, vous pouvez simplement avoir une colonne d'identité qui commence à 100000000. Vous pouvez également utiliser SQL dans votre base de données. Obtenez juste l'ID max plus 1.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top