IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Bases de données Delphi Discussion :

Problème: trop de tables ouvertes


Sujet :

Bases de données Delphi

  1. #1
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 15
    Points : 12
    Points
    12
    Par défaut Problème: trop de tables ouvertes
    Bonjour. J'ai un petit soucis.


    J'ai une boucle qui parcours + de 300000 tuples d'une table.
    Dans cette table, les propriétés sont:
    - ref (identifiant auto-incrémenté)
    - lib (chaine initiale)
    - trait (chaine traitée)

    Pour l'instant, seules les colonnes ref et lib sont remplies.


    Le but de ma boucle est donc de récupérer, pour chaque tuple, la valeur de la chaine lib, de la traiter (à l'aide d'une fonction...), et une fois traitée, de faire un update sur ma table pour ajouter la chaine traitée trait sur la ligne du lib correspondant.


    Mon code, sous Delphi 7, est le suivant:

    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
    procedure TForm1.Button1Click(Sender: TObject);
    var
    i:integer;                            //Compteur de boucle
    sIn:string;                           //Chaine à traiter
    nbreint:integer;                      //Nombre de tuples de la table
    nbrestr:string;                       //nbreint convertir en string
     
     
    begin
    nbreint:=Query_nbreCOUNT.Value;
    nbrestr:=IntToStr(nbreint);
     
    for i:=1 to nbreint do
      begin
        with query_mot do
          begin
            //Active:=false;
            Params[0].Value:=i;
            ExecSQL;
            Active:=True;
            Open;
          end;
        mot:=query_motmot_lib.Text;
        query_mot.Active:=False;
        result:=convert(mot);
        query_trait.Params[0].Value:=result;
        query_trait.Params[1].Value:=i;
        query_trait.ExecSQL;
     
      end;
    end;

    La requete de mon query_nbre est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT COUNT(*)
    FROM mots

    La requete de mon query_mot est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT mot_lib
    FROM mots
    WHERE mot_num=:p

    La requete de mon query_trait est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    UPDATE mots
    SET mot_trait=:p
    WHERE mot_num=:q


    Lorsque j'exécute, il me retourne le message d'erreur suivant:
    Le projet importbdd.exe a provoqué une classe d'exception EDBEngineError avec le message 'Opération non applicable.
    Trop de tables ouvertes.
    Table: C:\...\mots.db'. Processus stoppé. Utilisez Pas-àpas ou Exécuter pour continuer.


    Cepedant, lorsque je donne à i une valeur fixe, donc sans faire de boucle, ça fonctionne parfaitement.
    Y'aurait-il un probleme face à un nombre très important de lignes, où est-ce moi qui ait fait une bourde qui fait que ma boucle plante ?


    J'ai bien sûr sur ma form le composant Ttable activé sur ma base mot.db et le composant Tdatasource lié à mon Ttable.

    A savoir aussi que je bosse avec une base Paradox.




    Merci de m'éclairer. Je pete un plomb depuis hier soir.


    Merci d'avance pour vos réponses.

  2. #2
    Membre du Club
    Inscrit en
    Mai 2005
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 49
    Points : 59
    Points
    59
    Par défaut
    N'est pas peur vieux ton raisonnement et logique à la limite pas faux. sauf que t'est sur une machine appelée PC (pour personal computer) donc t'as pas un SPARC. En plus tu attaque une base de données Paradox avec le BDE (je suppose).
    Dans ce genre de situation il faut garder à l’esprit qu’il faut consommer le moins de ressources possibles. Ce qui n’est pas ton cas. ta méthode consomme beaucoup de ressources (mémoire). il faut donc alléger la procedure et pour cela :
    1- Ton traitement concerne une seule table donc vaux mieux utiliser un TTable.
    2- T’as pas besoin d’une boucle for pour parcourir la liste des éléments de ta table (donc on éliminer une requête query_nbre avec Count(*) )
    3- la mise à jour peut être effectuée directement sur la TTable sans passer par query_trait

    En prenant en compte ces trois points je te propose le code suivant :
    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
    Procedure TraiterLesTuple(ATable :TDataSet) ;
    var
      RefFld,
      LibFld,
      TraitFld:TField;
      OriginalStr, 
      ResultStr:String;
    begin
      RefFld:=ATable.FieldByName('Ref'); // les references vers les champs 
      LibFld:= ATable.FieldByName('Lib');
      TraitFld:= ATable.FieldByName('Trait');
      ATable.First; // aller en debut de table
      while not ATable.Eof do // boucler sur l’ensemble
      begin
        OriginalStr:=LibFld.AsString; 
        ResultStr:= FonctionDeTraitement(OriginalStr); // Traiter la chaine
        TraitFld.AsString := ResultStr;
        ATable.Next; // Passer au tuple suivant
      end;
    end;

  3. #3
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 15
    Points : 12
    Points
    12
    Par défaut
    Merci. Je vais tester ça (enfin, je vais essayer de tester ça car je ne connais pas les composants que tu utilises, je n'ai pas pour habitude de bosser avec, d'où mes problèmes dus à l'utilisation de composants non adaptés. Enfin bref...)

    Je tiens au courant...

  4. #4
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 15
    Points : 12
    Points
    12
    Par défaut
    Un petit soucis au niveau de TraitFld := ResultStr; -> erreur Types incompatibles : 'TField' et 'String'

    Un moyen de passer outre ?

  5. #5
    Membre du Club
    Inscrit en
    Mai 2005
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 49
    Points : 59
    Points
    59
    Par défaut
    exuses mois, en copiant le code j'ai fait qq erreurs (mais j'ai rectifié).

    quelques precisions sur la procedure
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     Procedure TraiterLesTuple(ATable :TDataSet);
    j'ai utilisé le type TDataSet pour qu’elle soit générique; au fait TDataSet est l'ancêtre (l'arrière grand père) de tout les objets ensembles de données (ADO, BDE, IBExpress …). donc si tu attaque ta base avec des composant BDE ou ADO tu peu avoir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var 
      Table1 :TTable;
      ADOTable : TADOTable;
    begin
      ... 
      ... un peu de code
      ...
      TraiterLesTuple(Table1); // ça marche
      TraiterLesTuple(ADOTable1); // ça marche aussi
      ...
    end;
    la procedure marche dans les deux cas (sauf pour les composant dbExpress pour d'autres raisons)

  6. #6
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 15
    Points : 12
    Points
    12
    Par défaut
    Bon eh bien voilà.
    Ca a marché. L'intégralité de ma table a été traitée avec une rapidité déconcertante et sans aucun message d'erreur.

    Dès fois que ça puisse servir à d'autres, voici mon code:

    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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    unit import;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, DB, DBTables, StdCtrls, soundex, DBCtrls;
     
    type
      TForm1 = class(TForm)
        Button1: TButton;
        mot_tab: TTable;
        DSmot_tab: TDataSource;
        Edit1: TEdit;
        mot_tabMOT_NUM: TAutoIncField;
        mot_tabMOT_LIB: TStringField;
        mot_tabMOT_TRAIT: TStringField;
        procedure Button1Click(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    uses DateUtils;
     
    {$R *.dfm}
     
     
     
     
    procedure TForm1.Button1Click(Sender: TObject);
     
    var
      RefFld:TField;
      LibFld:TField;
      TraitFld:TField;
      OriginalStr, ResultStr:String;
     
     
    begin
      RefFld:=mot_tab.FieldByName('MOT_NUM');       // Références vers les champs
      LibFld:= mot_tab.FieldByName('MOT_LIB');
      TraitFld:= mot_tab.FieldByName('MOT_TRAIT');
      mot_tab.First;                                // Aller en début de la table
      while not mot_tab.Eof do                      // Boucler sur l’ensemble
        begin
          OriginalStr:=LibFld.AsString;
          ResultStr:=convert(OriginalStr);
          mot_tab.Edit;
          TraitFld.AsString := ResultStr;
          mot_tab.Next;                             // Passer au tuple suivant
        end;
      Edit1.Text:='Process terminé';
    end;
     
     
     
     
    end.

    Problème résolu. Et encore merci beaucoup à toi chebreg !!!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Oracle10g Spatial] Problème : Trop de curseurs ouverts
    Par NeraOne dans le forum Administration
    Réponses: 7
    Dernier message: 15/05/2007, 12h12
  2. Trop de fichiers ouverts ...
    Par djidji dans le forum C
    Réponses: 4
    Dernier message: 01/12/2005, 17h15
  3. [RESULTSET]ORA-001000 trop de curseurs ouverts
    Par elitost dans le forum JDBC
    Réponses: 7
    Dernier message: 30/06/2005, 13h54
  4. Problème d'alter table dans une procédure stockée
    Par Oluha dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 16/03/2005, 09h19
  5. Problème avec mes tables de relation...
    Par mmike dans le forum PostgreSQL
    Réponses: 4
    Dernier message: 02/06/2003, 15h16

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