Mémoire insuffisante

Résolu
Uryon Messages postés 77 Statut Membre -  
Uryon Messages postés 77 Statut Membre -
Bonjour à tous,

actuellement stagiaire je dois réaliser un module de gestion des doublons de la base de donnée de mon entreprise. Je travaille sous Access 2007 et j'ai pour le moment bien avancé dans le projet (J'ajoute à une table Nomtable_doublon les doublons de la table Nomtable puis je supprime les doublons de NomTable avant de réajouter après traitement tous les doublons unitaires dans Nomtable à partir de Nomtable_doublon).
Le programme fonctionne correctement jusqu'à ce qu'il m'affichage une erreur mémoire insuffisante la base de donnée est peut être endommagée...
De ce que j'ai pu récolter sur internet ça serait dû au fait que je dépasse les 2Go (malgré le fait que je compacte la base de donnée avant tout traitement), j'ai essayé de fractionner la base de données mais après vérification la taille de la base de donnée contenant les formulaires n'a pas diminuée.
Auriez-vous une idée de comment résoudre mon problème de mémoire ? Ferais-je mal le traitement? Pourrais-je augmenter la mémoire maximum ?

D'avance merci.
Uryon.

6 réponses

  1. Sugel Messages postés 4293 Date d'inscription   Statut Membre Dernière intervention   728
     
    0
    1. Sugel Messages postés 4293 Date d'inscription   Statut Membre Dernière intervention   728
       
      D'autres disent de créer une nouvelle base en important tout le contenu de l'ancienne.
      0
  2. Uryon Messages postés 77 Statut Membre
     
    J'ai du mal expliqué, je peux démarrer Access sans soucis, le problème a lieu lorsque j'éxécute le programme (au bout d'un certains temps de traitement, j'ai conclu que c'était quand le fichier dépassait les 2Go)
    0
    1. Sugel Messages postés 4293 Date d'inscription   Statut Membre Dernière intervention   728
       
      Je n'ai absolument aucune connaissance Access, mais ne peut-tu pas fragmenter ce programme ? Histoire de contourner cette limitation ?
      0
    2. Uryon Messages postés 77 Statut Membre
       
      C'est la solution que j'experimente actuellement en ayant trouvé un post sur ce forum mais j'avoue que ce n'est pas très propre et cela pose un problème au niveau de l'ouverture.
      Sauf si je me trompe à chaque fois qu'Access éxécute un programme en rapport avec une table liée il ouvre et referme la base liée, ce qui rajoute du temps de traitement je crois et étant donné que le traitement est déjà relativement long j'aurais aimé une meilleure alternative.
      0
  3. Tessel75
     
    Bonjour,
    Les tutoriels disent habituellement que la capacité maxi de Access est de 1Go voire 750 Mo . Le seul moyen qui te reste est de fragmenter, par exemple les tables sur l'une, les requêtes, formulaires, états, etc sur l'autre.
    Bonne suite
    0
  4. Uryon Messages postés 77 Statut Membre
     
    Actuellement j'ai fractioné la base en deux : L'une contient les tables de base et l'autre toutes les tables, requêtes et formulaires contenant le traitement, on verra si ça fonctionne correctement si vous me dites qu'il n'y a pas d'autre solutions.
    Merci à vous.
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. blux Messages postés 5032 Date d'inscription   Statut Modérateur Dernière intervention   3 455
     
    Salut,

    tu fais tes modifs avec quelle méthode : requêtes standard ou requêtes en VBA avec/sans journalisation (commit/rollback) ?
    0
  7. Uryon Messages postés 77 Statut Membre
     
    Alors excusez moi mais je ne suis que débutant donc je ne connais pas exactement les termes...
    Pour effectuer les modifications j'ai choisi de parcourir un recordset contenant tous les doublons (Avec un identifiant unique pour chaque ligne), je crée alors deux recordsets : L'un contenant la première itération du doublon, le deuxième la seconde je passe les détails de priorité des données mais en clair si un champ du premier est nul alors je remplace par la valeur du deuxième. Je met donc à jour ce premier doublon avant de passer au doublon suivant, en mettant à jour le deuxieme recordset,
    si le premier et le troisieme sont des doublons alors on recommence la manip
    si le premier et le troisieme ne sont pas des doublons alors je remplace le premier par le troisieme et je passe au suivant
    Ainsi de suite jusqu'à la fin du fichier.
    Quand un doublon est à supprimer (ici ce serait le deuxieme par exemple) je l'ajoute à une table, si il est à garder (le premier) je le met dans une autre.
    A la fin du programme j'ajoute à la table de base les doublons que j'ai conservé.
    0
    1. blux Messages postés 5032 Date d'inscription   Statut Modérateur Dernière intervention   3 455
       
      Il est donc probable que les mises à jour multiples provoquent une inflation des pointeurs de gestion de la base.
      Il serait intéressant de mettre quelques 'commit' pour voir si le comportement est le même...
      0
    2. Uryon Messages postés 77 Statut Membre
       
      Je suis allé fouiner un peu sur internet et j'ai trouvé que les "commit" avaient rapport à des transactions mais je ne sais pas ce que c'est et je n'ai pas trouvé...
      De ce que j'ai pu comprendre le "commit" sert à effectuer les modifications désirées sur les enregistrement c'est ça?
      0
    3. blux Messages postés 5032 Date d'inscription   Statut Modérateur Dernière intervention   3 455
       
      Le commit sert à garantir une cohérence dans les mises à jour multiples. C'est la base d'une transaction ACID.
      Je mettrais un peu de commit mais avant je remettrais les objets recordset à zéro de temps en temps.
      Il serait quand même intéressant qu'on voie ton code pour se faire une idée de ce qu'il est possible de faire pour éviter ce problème.
      0
    4. Uryon Messages postés 77 Statut Membre
       
      Je met le code juste après ce message.
      J'ai réussi à trouver un site m'expliquant l'utilité des transactions.
      Le problème c'est qu'ici, selon certains critères (Date de saisie, ID la plus élevée, valeur d'un champ) je dois modifier certains champs (Si un champ est vide, nulle ou égal à 0 on le remplace par l'autre afin de ne pas perdre de données) je pense donc ne pas pouvoir utiliser les transactions dans ce cas car elles ne me permettraient pas de modifier seulement une partie de la ligne non?
      0
    5. Uryon Messages postés 77 Statut Membre
       
      'Permet de supprimer les doublons en fonction du telephone_standard 
      Private Sub dbl_telephone_Click() 
      Dim db As Database 
      Set db = CurrentDb() 
      Dim idPrec As String 'ID de la societe qu'on gardera 
      Dim IdActu As String 'ID de la societe qu'on supprimera 
      Dim sql As String 
      Dim rs As Recordset 
      Dim rsPrec As Recordset 
      Dim rsActu As Recordset 
      Dim rsPostal As Recordset 
      Dim rsSaisiePrec As Recordset 
      Dim rsSaisieActu As Recordset 
      Dim compteur As Long 
      Dim modif As Boolean 
      Dim i As Integer 
      Dim signaprec As Integer 
      DoCmd.SetWarnings False 'Permet de supprimer les avertissements lors de la modification, l'ajout, la suppression.... 
      
      
      DoCmd.RunSQL ("Delete * from doublonagarder;") 
      DoCmd.RunSQL ("Delete * from societe_doublon;") 
      'Insert dans societe_doublon les doublons en fonction du telephone_standard 
      DoCmd.RunSQL ("Insert INTO societe_doublon select * FROM societe WHERE (((societe.telephone_standard) In (SELECT [telephone_standard] FROM [societe] As Tmp GROUP BY [telephone_standard] HAVING Count(*)>1 ))) order by telephone_standard, id_societe DESC;") 
      
      'Initialisation 
      compteur = 0 
      modif = False 
      
      Set rs = db.OpenRecordset("Select * FROM societe_doublon order by telephone_standard, id_societe DESC") 
      If rs.EOF = True Then 
          MsgBox ("Il n'y a pas de doublons de sociétés ") 
      Else 
          rs.MoveFirst 
          idPrec = rs!id_societe 'On donne à idprec l'id_societe du premier enregistrement 
          rs.MoveNext 
          'Boucle qui parcourt toute la Base de données 
          Do While rs.EOF = False 
              IdActu = rs!id_societe 
              sql = "Select * FROM societe_doublon WHERE id_societe=" & idPrec & ";" 
              Set rsPrec = db.OpenRecordset(sql) 'Ligne qu'on gardera (idprec) 
              sql = "Select * FROM societe_doublon WHERE id_societe=" & IdActu & ";" 
             Set rsActu = db.OpenRecordset(sql) 'Ligne qu'on supprimera (idactu) 
             signaprec = rsPrec!signaletique_ok 
              'Si le telephone_standard est identique alors 
              If rsPrec!telephone_standard = rsActu!telephone_standard Then 
                  'ETAPE 1 : RsPrec est la ligne qu'on gardera, si un de ses champs est vide on le remplace par celui de RsActu 
                  rsPrec.Edit 
                      For i = 1 To rsPrec.Fields.Count - 3 
                          If IsNull(rsPrec.Fields(i).Value) = True Or rsPrec.Fields(i).Value = "" Or rsPrec.Fields(i).Value = 0 Then 
                              rsPrec.Fields(i).Value = rsActu.Fields(i).Value 
                          End If 
                      Next i 
                  rsPrec!signaletique_ok = signaprec 
                  rsPrec.Update 
                  'FIN DE L'ETAPE 1 
                   
                  'ETAPE 2 : On vérifie les signaletique_ok 
                  'On vérifie que signaletique_ok de rsActu est égal à 1, si c'est le cas et que celui de rsPrec est 0 alors on remplace les champs de rsPrec par ceux de rsActu 
                  If rsPrec!signaletique_ok = 0 And rsActu!signaletique_ok = 1 Then 
                      modif = True 
                  End If 
                   
                  'Si signaletique_ok de rsprec et de rsActu ont la même valeur 
                  If (rsPrec!signaletique_ok = 1 And rsActu!signaletique_ok = 1) Or (rsPrec!signaletique_ok = 0 And rsActu!signaletique_ok = 0) Then 
                  Set rsSaisieActu = db.OpenRecordset("Select date_saisie FROM actions WHERE id_societe=" & IdActu & " ORDER BY date_saisie DESC;") 'Date de saisie de rsActu 
                  Set rsSaisiePrec = db.OpenRecordset("Select date_saisie FROM actions WHERE id_societe=" & idPrec & " ORDER BY Date_saisie DESC;") 'Date de saisie de rsPrec 
                  'On vérifie que rsprec et rsActu ont une date de saisie 
                      If rsSaisiePrec.EOF = False And rsSaisieActu.EOF = False Then 
                      rsSaisiePrec.MoveFirst 
                      rsSaisieActu.MoveFirst 
                          'Si la date de saisie de RsActu est plus récente que celle de rsPrec alors on remplace les champs de rsprec par ceux de rsactu 
                          If rsSaisiePrec!date_saisie < rsSaisieActu!date_saisie Then 
                              modif = True 
                          End If 
                      End If 
                  rsSaisieActu.Close 
                  rsSaisiePrec.Close 
                  End If 
                  'FIN DE L'ETAPE 2 
                  'ETAPE 3 : On modifie les champs de rsPrec par ceux de rsActu si il le faut 
                  If modif = True Then 
                      rsPrec.Edit 
                          For i = 1 To rsPrec.Fields.Count - 3 
                              If IsNull(rsActu.Fields(i).Value) = False And rsActu.Fields(i).Value <> "" And rsPrec.Fields(i).Value <> 1 Then 
                                  rsPrec.Fields(i).Value = rsActu.Fields(i).Value 
                              End If 
                          Next i 
                      rsPrec.Update 
                  End If 
                  'FIN DE L'ETAPE 3 
                  'ETAPE 4 : On vérifie que si le pays est la France, alors le code postal concorde avec les deux premiers numéros du telephone_standard 
                  If rsActu!pays = "France" Then 
                      sql = "Select * FROM TablePostal WHERE code_Postal='" & Left(rsPrec!code_postal, 2) & "';" 
                      Set rsPostal = db.OpenRecordset(sql) 'Ligne contenant l'indice téléphonique pour le code postal du rsPrec 
                      If rsPostal.EOF = False Then 
                          'Si l'indice du téléphone et le code postal ne correspondent pas alors on remplace le code postal de rsPrec par celui de rsActu 
                          If Left(rsPrec!tel2, 2) <> rsPostal!indice_tel Then 
                              rsPrec.Edit 
                                  rsPrec!code_postal = rsActu!code_postal 
                                  rsPrec!ville = rsActu!ville 
                              rsPrec.Update 
                              rsPostal.Close 
                          End If 
                      'Si le code postal de rsPrec ne correspond à aucun indice de téléphone alors on remplace le code postal de rsPrec par celui de rsActu 
                      Else 
                          rsPrec.Edit 
                              rsPrec!code_postal = rsActu!code_postal 
                              rsPrec!ville = rsActu!ville 
                          rsPrec.Update 
                          rsPostal.Close 
                      End If 
                  End If 
                  'FIN DE L'ETAPE 4 
                   
                  rsPrec.Close 
                  rsActu.Close 
                  DoCmd.RunSQL ("Update societe_doublon SET doublon=1 WHERE id_societe=" & IdActu & ";") 
                  DoCmd.RunSQL ("Update societe_doublon SET doublon=2 WHERE id_societe=" & idPrec & ";") 
                  compteur = compteur + 1 
                  DoCmd.RunSQL ("Insert INTO TableCorrespondance (ID_ancienne,ID_nouvelle) values (" & IdActu & "," & idPrec & ");") 
              Else 
                  'Si ce n'est pas un doublon alors on donne à idprec la valeur d'idactu 
                  rsPrec.Close 
                  rsActu.Close 
                  idPrec = IdActu 
              End If 
          rs.MoveNext 
          Loop 
      End If 
      rs.Close 
      DoCmd.RunSQL ("Insert INTO DoublonAjeter Select * FROM societe_doublon WHERE doublon=1 AND id_societe NOT IN (Select ID_societe FROM doublonajeter);") 
      DoCmd.RunSQL ("Insert INTO DoublonAgarder Select *  FROM societe_Doublon WHERE doublon=2 AND id_societe NOT IN (select id_societe FROM doublonagarder);") 
      DoCmd.RunSQL ("Delete * from societe WHERE id_societe IN (Select id_societe FROM societe_doublon);") 
      DoCmd.RunSQL ("Insert INTO societe select * from doublonagarder;") 
      MsgBox ("Il y a eu " & compteur & " doublons supprimés") 
      
      End Sub
      0