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 :

CalculateField à la "volé"


Sujet :

Bases de données Delphi

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2003
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 560
    Points : 576
    Points
    576
    Par défaut CalculateField à la "volé"
    Bonjour,

    J'ouvre des requêtes SQL via un TADOQUERY.

    Je laisse l'ADOQUERY constituer automatiquement les champs, car je ne sais pas avant l'ouverture les champs qui seront retourner (Select * from ..). Les tables ne sont jamais identique

    si je crée un champs calculer avant d'ouvrire le TAdoquery, les champs lus ne sont pas crées automatiquement.

    si j'essaye de crée le champs calculé aprés l'ouverture (dans After open), l'association de champs au dataset ne peut pas être effecuter car le dataset est actif.

    en 1 mot comme en 100, je tourne en rond. sans avoir que faire pour m'en sortir.

    Voila le code que j'utilise pour créer le champs calculé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
      if FRecNo = nil then begin
        FRecNo := TStringField.Create(self);
        FRecNo.FieldName :=  'RecNoRecNoRecNoRecNoRecNoRecNo';
        FRecNo.DisplayLabel := 'Rec. No.';
        FRecNo.Name := Adoquery.Name + 'NomChamps';
        FRecNo.Size := 255;
        FRecNo.FieldKind := fkCalculated;
        FRecNo.DataSet := Adoquery;
      end;
    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 455
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 455
    Points : 24 867
    Points
    24 867
    Par défaut
    tu peux essayer avec le "Select * from" de faire 'Select *, "0" as Dummy from' ainsi tu auras un bidon (cela fonctionne en MySQL) que tu peux ainsi modifier au moment opportun ... perso, je préfère cette méthode car j'ai toujours eu des chiasses avec les Calculated car soit la lib de la société qui m'employait ne les supportaient mal (composant DB hérité du TClientDataSet) ...

    même en paradox, c'est possible, juste que * ne fonctione plus, mais il suffit de faire une requête donnant la liste des champs, pour générer son SQL explicite ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2003
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 560
    Points : 576
    Points
    576
    Par défaut
    Créer un champs fixe, oui pourquoi pas, mais comment faite vous pour luis attribuer une valeur par la suite ?

    Je vois pas bien comment faire, cependant en attendant votre réponse je vais quand même essayer de trouver.

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 455
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 455
    Points : 24 867
    Points
    24 867
    Par défaut
    Eh, bien, je fais une boucle qui lance le calcul, et je modifie le DataSet, bon attention, il faut qu'il soit en mode cache, en ADO, je ne sais pas trop, je ne le faisais que sur des ClientDataSet ou sur les composant MyDAC de CoreLab

    après sinon, tu peux aussi faire des sous requêtes, je l'ai fait aussi pour des calculs de %

    'Select *, (Select Count(*) from machin where Machin.cle = Chose.Clé) as Dummy from Chose'

    sinon il reste le faire en deux temps

    tu fais un 'Select * from truc where 0', cela te donne la structure de la table (tu peux stocker cela dès l'ouverture du programme), tu créé les colonnes dans ton DBGrid ... puis tu relance la vrai requête ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 419
    Points : 5 818
    Points
    5 818
    Par défaut
    salut

    tu veut faire un truc du genre ?
    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
     
     
    procedure Initialiser(const aFieldName : string ; 
                    const aDataSet : TDataSet ; 
                    const aDataSetNotifyEvent : TDataSetNotifyEvent) ; 
    var 
      i : integer ; 
    begin 
      if (not aDataSet.FieldDefs.Updated) then 
      begin 
        aDataSet.FieldDefs.Update ; 
     
        for i := 0 to aDataSet.FieldDefs.Count - 1 do 
        begin 
          aDataSet.FieldDefs[i].CreateField(aDataSet) ; 
        end ; 
     
        with TFloatField.Create(aDataSet) do 
        begin 
          FieldName := aFieldName ; 
          Name := aDataSet.Name + FieldName ; 
          Calculated := True ; 
          DataSet := aDataSet ; 
        end ; 
      end ; 
     
      aDataSet.OnCalcFields := aDataSetNotifyEvent ; 
    end ; 
     
    avec 
    ..... 
    procedure TForm1.Table1CalcFields(DataSet: TDataSet); 
    begin 
      DataSet.FieldByName('SOLDE').AsFloat := DataSet.FieldByName('COMPTE1').AsFloat + DataSet.FieldByName('COMPTE2').AsFloat ; 
    end; 
    ..... 
    procedure TForm1.FormShow(Sender: TObject); 
    begin 
      Database1.Connected := True ; 
      Initialiser('SOLDE', Table1, Table1CalcFields) ; 
      Table1.Active := True ; 
    end;

    cela devrai marcher pour un query aussi

    @+ Phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2003
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 560
    Points : 576
    Points
    576
    Par défaut
    Bonjour,

    Ou, cela fonctionne, mais l'ajout du chaqamps calculé est fait avant le "Table.Ative := true;" .
    Par conséquence les champs du select ne sont pas créer automatiquement.

    Pour l'instant, la seule solution que j'ai pus trouver, consiste à ouvrir un TAdoQuery, a copier le format des champs dans un autre ADOQuery, a ajouter les champs calculer dans le nouveau query puis à l'ouvrir avec la même requête.

    Eventuellment je peux essayer un teste idot telle que "Where 1= 2" dans la requête du 1° Adoquery, cela m'éviterai de ramener des enregistrements (juste le format de la table).
    Cela devrait fonctionner, mais ce n'est pas terrible comme solution, et certaines connections peuvent être très longue. alor ce connecter 2 fois, ce n'est pas le pied.

  7. #7
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Mars 2004
    Messages
    897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 897
    Points : 1 561
    Points
    1 561
    Par défaut
    Citation Envoyé par Tardiff Jean-François
    Cela devrait fonctionner, mais ce n'est pas terrible comme solution, et certaines connections peuvent être très longue. alors ce connecter 2 fois, ce n'est pas le pied.
    Si tu utilises un TADOQuery, tu peux utiliser le propriété MaxRecords qui te permet de spécifier le nombre maximum de lignes à renvoyer dans un ensemble de résultats. En lui mettant la valeur 1, ton ensemble de résultats ne sera constitué au maximum que d'une ligne, ce qui te fera gagner du temps de traitement.

    Par ailleurs, et pour la question que tu as posé initialement, personnellement je créerai directement les champs calculés dans la requête de la façon suivante :

    select *, champi op champj as "mon premier champ calculé",...

    Cordialement
    Pensez à utiliser les tags dans le titre.
    Avant de poser une question reportez-vous à la FAQ Delphi
    Respectez les règles du forum.

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2003
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 560
    Points : 576
    Points
    576
    Par défaut
    Le temps de connections ne dépend pas que du nombre d'enregistrement rapatrié. L'application est censée pouvoir ce connecté à n'importe quelle base via ADO. J'ai déjà vue des connections à distance prendre le même temps, pour se connecter, que le fût du canon, pour refroidir. (Pour ceux qui ne connaissent pas leurs classiques, cela signifie un certain temps).

    Donc je me méfie du résultat en exploitation et minimise les connections.

    De même je ne connais pas les nom des champs avant l'ouverture de la table. Donc je ne peux pas utilise de nom précis Dans ma requête.

    Enfin je ne peux, ou je ne sais, pas modifier un type de champs dans une TDataSet actif. Donc je ne peux pas créer un champs "bidon" dans ma requête pour en changer le type.

    Je crois que vous calculé une requête renvoyant un champs calculé, et un champs calculé delphi (Tfield avec calculated = true)

  9. #9
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 419
    Points : 5 818
    Points
    5 818
    Par défaut
    salut


    si j'ai bien compris tu ne connait pas a l'avance les champs que tu veut utiliser
    ?

    et ensuite a ta requette tu veut creer dynamiquement un champs calcule
    tu ne pourrait pas de la meme maniere creer tes champs persistant et ton champs calculé

    @+ Phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2003
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 560
    Points : 576
    Points
    576
    Par défaut
    C'est bien ce que je vais être obligé de fair. Mais comme je ne sais même pas les champs (nom, type, longueur etc..) qu'il y à dans les tables, cela veut dire que je vais être obligé d'ouvrir la table pour voir les champs existant. De les créer dans un autre ADOQuery, puis de créer les champs calculé nécessaire pour le traitement (n° unique, boite a cocher etc.). En théorie, cela devrait être rapide, car les connections devraient être local. En pratique je n'ai pas confiance dans de telle assertion.
    Le pire c'est que je ne devrait même pas si j'aurais un index unique pour repérer mes enregistrements.
    Le B... absolue sans analyse préalable, sans cahier des charges

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