1. #1
    Rédacteur

    Avatar de Tofalu
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    octobre 2004
    Messages
    9 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Associations - ONG

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 502
    Points : 32 115
    Points
    32 115

    Par défaut [Exercice] Numérotation automatique d'enregistrements

    Bonjour,

    Je vous propose un petit exercice :

    Comment procederiez vous pour avoir une table offrant 3 identifiants par enregistrement ?

    • Le champ 1 serait un numéro auto croissant
    • Le champ 2 serait un numéro aléatoire
    • Le champ 3 serait un autre numéro aléatoire


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    N1	N2	N3	Libelle
    1	-858043924	-436861315	Chien
    2	1683190266	-1215191821	Chat
    3	-594784072	1798275161	Baleine
    Notez que des valeurs de N1 peuvent se trouver dans N2 ou N3 et vice versa. Par contre, une valeur de N2 ne peut se répeter dans N2 et idem pour les deux autres colonnes.

    Des idées ?

    Si possible, j'aimerais que la solution que vous proposiez puisse s'adapter facilement à d'autres champs, genre une dizaine

  2. #2
    Membre chevronné
    Inscrit en
    août 2006
    Messages
    1 552
    Détails du profil
    Informations forums :
    Inscription : août 2006
    Messages : 1 552
    Points : 2 113
    Points
    2 113

    Par défaut

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
    Sub NouvelEnregistrement(animal As String)
     Dim n As Long, i As Integer, j As Integer, max As Long,NbChamp As Integer
     Dim db As DAO.Database, t As DAO.Recordset, t2 As DAO.Recordset
     Set db = CurrentDb
     
     NbChamp = 5                                      'Nombre de champs N
     max = DMax("[N1]", "tbAnimaux") + 1       'recherche N1 suivant
     Set t = db.OpenRecordset("tbAnimaux")
     t.AddNew
     t!N1 = max         'champ auto croissant
     
     For j = 2 To NbChamp      'pour chacun des champs N
     
      Do    '##################
     
       If Rnd(1) > 0.5 Then     'sélection du signe
        n = Rnd(1) * 2147483647
       Else
        n = Rnd(1) * -2147483647
       End If
     
       For i = 2 To NbChamp    'recherche presence du nombre n
        Set t2 = db.OpenRecordset("SELECT tbAnimaux.N" & CStr(i) & " FROM tbAnimaux WHERE (((tbAnimaux.N" & CStr(i) & ")=" & n & "));")
        If Not t2.EOF Then t2.Close: Exit For
        t2.Close
       Next i
        If i = 6 Then Exit Do    'nombre n'existe pas
     
      Loop  '####################
     
      t("N" & CStr(j)) = n         'enregistrement du nombre n dans champ N
     Next j
     
     t!texte = animal 
     t.Update
     
     t.Close
     Set t = Nothing
     Set db = Nothing
    End Sub

  3. #3
    Rédacteur

    Avatar de Tofalu
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    octobre 2004
    Messages
    9 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Associations - ONG

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 502
    Points : 32 115
    Points
    32 115

    Par défaut

    Bonjour,

    Cette solution ne me satisfait qu'à moitié car peu réutilisable.

    Peut être serait t'il possible de la transformer en fonction qui accepteraient comme argument :

    Le nom du champ,
    Celui de la table
    Le type d'incrémenation


    Genre

    DIncrement("N1","MaTable",0) renverrai un numéro autoincrémenté valide
    DIncrement("N2","MaTable",1) renverrai un numéro aléatoire valide

    Reste à voir comment utiliser cette fonction facilement dans un formulaire, et aussi lister les avantages et ses inconvénients pour les données

    En tout cas, merci de ta participation

  4. #4
    Membre chevronné
    Inscrit en
    août 2006
    Messages
    1 552
    Détails du profil
    Informations forums :
    Inscription : août 2006
    Messages : 1 552
    Points : 2 113
    Points
    2 113

    Par défaut

    Avec dans le formulaire pour les champs la valeur par defaut =Dincrement("tbTest";0) pour l'increment simple et =Dincrement("tbTest";1) pour le nombre aleatoire

    Les champs testés pour le nombre aleatoire sont les champs dont le nom se terminent par un nombre à partir du 2ème caractère
    N12 est valide, B13 aussi, as12 ou n15d ne le sont pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    Function DIncrement(NomTable As String, TypeIncrement As Integer) As Long
     
     Select Case TypeIncrement
     Case 0
      DIncrement = DMax("N1", NomTable) + 1
     
     Case 1
      Dim i As Integer, NbChamps As Long
      Dim db As DAO.Database, t As DAO.Recordset
     
      Set db = CurrentDb
      Set t = db.OpenRecordset(NomTable)
      NbChamps = 0
     
      For i = 0 To t.Fields.Count - 1
       If IsNumeric(Mid$(t.Fields(i).Name, 2)) Then NbChamps = NbChamps + 1
      Next i
     
      Randomize
      Do    '##################
     
       DIncrement = (Rnd(1) * 2147483647) * IIf(Rnd(1) > 0.5, 1, -1) 'genere le nombre aleatoire
     
       For i = 2 To NbChamps   'recherche presence du nombre
        Set t = db.OpenRecordset("SELECT [" & NomTable & "].N" & CStr(i) & " FROM [" & NomTable & "] WHERE (([" & NomTable & "].N" & CStr(i) & ")=" & DIncrement & ");")
        If Not t.EOF Then t.Close: Exit For
        t.Close
       Next i
       If i = NbChamps + 1 Then Exit Do  'nombre n'existe pas
     
      Loop  '####################
     
      Set t = Nothing
      Set db = Nothing
     End Select
    End Function

  5. #5
    Rédacteur
    Avatar de LedZeppII
    Homme Profil pro
    Maintenance données produits
    Inscrit en
    décembre 2005
    Messages
    4 485
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Maintenance données produits
    Secteur : Distribution

    Informations forums :
    Inscription : décembre 2005
    Messages : 4 485
    Points : 7 621
    Points
    7 621

    Par défaut

    Bonjour,

    voila ma proposition.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Function NouvId(Table, Champ, Optional Incr = 1) As Long
    Dim s As Single, vMax As Variant
    If Incr = 1 Then
        Randomize
        Do
           s = Rnd() * 4294967294#
           If s > 2147483647 Then s = -s
           NouvId = CLng(s / 2)
        Loop Until IsNull(DLookup(Champ, Table, Champ & "=" & NouvId))
    Else
        vMax = DMax(Champ, Table)
        NouvId = IIf(IsNull(vMax), 0, vMax) + 1
    End If
    End Function
    A+

  6. #6
    Rédacteur

    Avatar de Tofalu
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    octobre 2004
    Messages
    9 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Associations - ONG

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 502
    Points : 32 115
    Points
    32 115

    Par défaut

    Helas, ta solution ne tiens pas compte du nom du champ à passer en paramètre. De ce fait, la solution de LedZeppII me parait meilleure, toutefois, reste une question, comment allez vous l'utiliser ?

  7. #7
    Membre chevronné
    Inscrit en
    août 2006
    Messages
    1 552
    Détails du profil
    Informations forums :
    Inscription : août 2006
    Messages : 1 552
    Points : 2 113
    Points
    2 113

    Par défaut

    Je pensais que le nombre aleatoire devait être unique dans toute la table, c'est pourquoi je testais aussi les autres champs Nn

    La version de LedZeppII est effectivement meilleur

    Pour l'utilisation dans un formulaire, Valeur par defaut = DIncrement(....)

  8. #8
    Rédacteur

    Avatar de Tofalu
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    octobre 2004
    Messages
    9 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Associations - ONG

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 502
    Points : 32 115
    Points
    32 115

    Par défaut

    Pour l'utilisation dans un formulaire, Valeur par defaut = DIncrement(....)
    Arf, et si je ne veux pas passer par un formulaire ?

  9. #9
    Membre chevronné
    Inscrit en
    août 2006
    Messages
    1 552
    Détails du profil
    Informations forums :
    Inscription : août 2006
    Messages : 1 552
    Points : 2 113
    Points
    2 113

    Par défaut

    Passer par quoi ?
    Du code ?

  10. #10
    Expert confirmé

    Profil pro
    Inscrit en
    mai 2005
    Messages
    3 419
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2005
    Messages : 3 419
    Points : 4 212
    Points
    4 212

    Par défaut

    champ1 numéro auto incrément
    champ2 double valeur par défaut rnd() indexé sans doublon
    champ3 double valeur par défaut rnd() indexé sans doublon

    reste à gérer les improbables conflits
    Elle est pas belle la vie ?

  11. #11
    Rédacteur

    Avatar de Tofalu
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    octobre 2004
    Messages
    9 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Associations - ONG

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 502
    Points : 32 115
    Points
    32 115

    Par défaut

    Citation Envoyé par random
    champ1 numéro auto incrément
    champ2 double valeur par défaut rnd() indexé sans doublon
    champ3 double valeur par défaut rnd() indexé sans doublon

    reste à gérer les improbables conflits

    Ah ben là c'est clairement déjà mieux puisque d'une part il est possible d'ajouter les données directement dans la table et d'autre part l'index permet de garantir l'intégrité des données.

    Seul bémol effectivement il faut gérer les conflits très improbable. Ce n'est pas vraiment à cette solution que je pensais mais celle ci n'est pas mal du tout

  12. #12
    Expert confirmé

    Profil pro
    Inscrit en
    mai 2005
    Messages
    3 419
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2005
    Messages : 3 419
    Points : 4 212
    Points
    4 212

    Par défaut

    Après test et 510 0000 enregistrements ajoutés en plusieurs passes pas de conflit.

    Comme disent les statisticiens « un évènement improbable ne se produit jamais »
    Elle est pas belle la vie ?

  13. #13
    Rédacteur

    Avatar de Tofalu
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    octobre 2004
    Messages
    9 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Associations - ONG

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 502
    Points : 32 115
    Points
    32 115

    Par défaut

    Peut être existe t'il une solution qui permettrait d'être sûr qu'aucun doublon ne sera généré

  14. #14
    Expert confirmé

    Profil pro
    Inscrit en
    mai 2005
    Messages
    3 419
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2005
    Messages : 3 419
    Points : 4 212
    Points
    4 212

    Par défaut

    en testant ceci pour champ1=1 à 3000000

    champ2=rnd(-champ1)
    champ3=rnd(-champ2)

    on trouve 3556 doublons sur champ2

    ceci provient de la piètre qualité du générateur de nombres aléatoires de microsoft
    en examinant les résultats on s'aperçoit que les doublons sont de la forme
    x, (x*2^y)-1
    genre
    valeur valeur doublon
    8....... 2097151
    17..... 1114111
    18...... 1179647
    19.... 1245183
    .....
    11718 2999807

    le plus grand nombre ayant un doublon qui lui est supérieur est donc
    11718 sur l'intervalle choisi
    conclusion
    si je définis
    champ2=rnd(-champ1-11718)
    champ3=rnd(rnd(-champ1-11718))
    je dispose de deux clefs pseudo aléatoires et d'un compteur

    auqel cas mettre ces clefs dans la base serait inutile
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT champ1, Rnd(-[champ1]-11718) AS champ2, Rnd(Rnd(-[champ1]-11718)) AS champ3
    FROM matable;
    permettant de retrouver à tous moments les clefs

    nb à ne pas utiliser en sécurité ni en cryptographie sans bien bien réfléchir
    Elle est pas belle la vie ?

  15. #15
    Rédacteur

    Avatar de Tofalu
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    octobre 2004
    Messages
    9 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Associations - ONG

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 502
    Points : 32 115
    Points
    32 115

    Par défaut

    C'est pas mal, mais je pense qu'on devrait pouvoir arriver à quelque chose garantissant encore plus le non doublonnage

  16. #16
    Expert confirmé
    Avatar de vodiem
    Homme Profil pro
    Vivre
    Inscrit en
    avril 2006
    Messages
    2 861
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Vivre
    Secteur : Conseil

    Informations forums :
    Inscription : avril 2006
    Messages : 2 861
    Points : 4 394
    Points
    4 394

    Par défaut

    une table avec
    un champ N1, un champ N2, un champ N3, un champ Libelle

    tous Indexé sans doublons

    Libelle: (taille du champ:texte)
    N1: taille du champ:NuméroAuto
    N2: taille du champ:réel simple / valeur defaut:Aléat()
    N3: taille du champ:réel simple / valeur defaut:-Aléat() / valide si:<>0

    N1 sera toujours >=1
    N2 n'atteindra jamais la valeur 1 et >=0
    N3 sera toujours négatif et <>0

    c pas dis le type du nombre aléatoire...

  17. #17
    Rédacteur

    Avatar de Tofalu
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    octobre 2004
    Messages
    9 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Associations - ONG

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 502
    Points : 32 115
    Points
    32 115

    Par défaut

    Oui mais rien n'empêche d'avoir deux fois le même N2 avec cette solution

  18. #18
    Expert confirmé
    Avatar de vodiem
    Homme Profil pro
    Vivre
    Inscrit en
    avril 2006
    Messages
    2 861
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Vivre
    Secteur : Conseil

    Informations forums :
    Inscription : avril 2006
    Messages : 2 861
    Points : 4 394
    Points
    4 394

    Par défaut

    et un truc comme ca:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DoCmd.RunSQL "INSERT INTO TABLE2(N2,N3) VALUES(" + Str(DMax("N1", "TABLE2") + 0.5 + (Rnd() / 2)) & "," & Str(DMax("N1", "TABLE2") + 0.49999999 - (Rnd() / 2)) + ")"
    a rajouter le labelle dans les valeurs bien sur...

  19. #19
    Rédacteur

    Avatar de Tofalu
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    octobre 2004
    Messages
    9 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Associations - ONG

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 502
    Points : 32 115
    Points
    32 115

    Par défaut

    Citation Envoyé par vodiem
    et un truc comme ca:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DoCmd.RunSQL "INSERT INTO TABLE2(N2,N3) VALUES(" + Str(DMax("N1", "TABLE2") + 0.5 + (Rnd() / 2)) & "," & Str(DMax("N1", "TABLE2") + 0.49999999 - (Rnd() / 2)) + ")"
    a rajouter le labelle dans les valeurs bien sur...

    Oui mais il n'y a rien d'automatique dans cette solution. Que se passe t'il si l'utilisateur veut saisir les données dans un formulaire ou dans la table directement ?

  20. #20
    Rédacteur

    Avatar de Maxence HUBICHE
    Homme Profil pro
    Développeur SQLServer/Access
    Inscrit en
    juin 2002
    Messages
    3 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Développeur SQLServer/Access

    Informations forums :
    Inscription : juin 2002
    Messages : 3 842
    Points : 9 180
    Points
    9 180

    Par défaut

    Citation Envoyé par Tofalu
    Comment procederiez vous pour avoir une table offrant 3 identifiants par enregistrement ?
    C'est pas normatif !
    Je ne fais pas !


Discussions similaires

  1. Fichier avec numérotation automatique et enregistrement
    Par ilankolins dans le forum Macros et VBA Excel
    Réponses: 0
    Dernier message: 29/11/2012, 20h55
  2. Réponses: 3
    Dernier message: 30/09/2010, 13h06
  3. Numérotation automatique d'enregistrement dans une requête
    Par Mobydisk21 dans le forum Requêtes et SQL.
    Réponses: 7
    Dernier message: 24/12/2009, 12h07
  4. Numérotation automatique selon les utilisateurs
    Par Safaritn dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 12/08/2005, 14h11
  5. suppression automatique des enregistrements
    Par abdou.sahraoui dans le forum Langage SQL
    Réponses: 4
    Dernier message: 02/08/2005, 13h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo