Mémoire insuffisante

Résolu
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. 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)
    1. Je n'ai absolument aucune connaissance Access, mais ne peut-tu pas fragmenter ce programme ? Histoire de contourner cette limitation ?
    2. 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.
  2. 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
    1. 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.
      1. Modérateur
        Salut,

        tu fais tes modifs avec quelle méthode : requêtes standard ou requêtes en VBA avec/sans journalisation (commit/rollback) ?
        1. 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é.
          1. Modérateur
            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...
          2. 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?
          3. Modérateur
            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.
          4. 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?
          5. '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