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 :

[D7] [Firebird 2.1] problème pour récuperer des champs calculés


Sujet :

Bases de données Delphi

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut [D7] [Firebird 2.1] problème pour récuperer des champs calculés
    Bonjour,

    Je développe des applications en Delphi 7. Celles-ci sont connectées à des bases de données en Firebird 2.1.
    Certaines tables contiennent des champs calculé via une procédure stockée.

    D'un point de vue base de données, ca a l'air OK: lorsque je consulte les table via un logiciel style EMS sql manager, je vois bien que des valeurs ont été calculées pour ces champs.

    Par contre, il arrive que dans Delphi, un Select champ_calculé from ma table where id = 'xx' ne retourne plus rien alors que le champs calculé n'est pas vide à la ligne dont l'id = 'xx' et qu’auparavant, il n'y avait pas de problème pour récupérer la valeur de ce champs calculé.

    En apparence, ce bug est apparu d'un plein coup dans un programme.

    Celui-ci contient un composant TIBOQuery où j'ai un
    select champs_1, champs_2, ... champs_n, champs_calc_1, champs_calc_2
    FROM
    MaTable
    Where ID = arametre;

    Dans delphi, lorsque j'utilise l'éditeur de query, où je prépare la query, puis lui passe les même paramètres que ceux passé lors de l'exécution du programme, et enfin affiche le résultat, je vois les valeurs calculées!

    Dans le programme on a une DBGrid liée au résultat de la query. Pour l'instant, elle n'affiche plus la valeur de champs_calc_2 .. par contre pas de problème pour champs_calc_1 (remarque : ces 2 champs sont calculé via une même procédure stockée).

    J'ai bien vérifié que la propriété Fieldname de la colonne du dbGrid a bien pour valeur "champs_calc_2", si je change en mettant "champs_calc_1" des valeurs apparaissent évidemment mais concernant "champs_calc2" ca a l'air vide (j'ai fais une boucle sur le resultat de la requete où j'affiche via un showMessage la valeur du champs, et il ne met rien valeur = '' ...).

    Anciennement cela s'était déja produit pour le même programme mais cette fois là, cela concernait "champs_calc1" et "champs_calc2".
    La solution d'urgence trouvée avait été de créer 2 champs data supplémentaire mis à jour lorsque la valeur du champs calculé était modifiée .. puis de modifier le select pour récupérer la valeur du champs data et non plus du champs calculé..

    Dans notre service, on a une base de données par année, et lorsqu'une année se clôture, on recopie la base de données en la renommant en fonction de la nouvelle année, on vide des tables, (etc..) puis on re-compile les programmes sur cette nouvelle base de données pour fournir de nouveaux programmes aux utilisateur.

    Suite à un nouveau programme, le bug "champs_calc1" et "champs_calc2" vide avait disparu ... et puis là, paf c'est revenu pour une raison que j'ignore, et cette fois pour "champs_calc2" uniquement.

    De mon point de vue, le code du programme est ok et du coté de la base de données, il y a bien des valeurs dans ces champs calculé.

    Se pose la question du pourquoi ca ne fonctionne pas ... plus.. (enfin à moitié cette fois!!)...

    Remarque: le serveur Firebird était anciennement sur un serveur Windows 2003 server, et il est depuis cette année sur windows server 2008.
    La version du serveur Firebird n'a pas changé (2.1.3.18185).

    Avez-vous déjà rencontré ce type d'erreur?
    Avez-vous des pistes à me suggérer??

    Merci d'avance pour les pistes que vous pourrez me donner.
    Sébastien

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Lorsque tu parles de champs calculés, cela a-t-il un apport avec OnCalcFields ou InternalCalcField
    OnCalcFields étant interne à Delphi
    InternalCalcField indiquant que le champ est issu d'une formule genre "A + B as C" et non directement un champ de la DB

    Comment fais-tu le lien entre ces champs et les procédures stockées, c'est directement dans le SELECT ou tu appels manuellement les procédures stockées dans OnCalcFields

    Le TDBGrid contient des colonnes prédéfinies ou c'est générer à la volée lors de l'ouverture du Query ?

    le TIBOQuery contient des champs persistants ou ils sont construit lors du Open ?
    TIBOQuery est bien différent du TIBQuery (Interbase Express) qui n'est pas conseillé pour FB dont on recommande l'accès avec UIB (si il n'existe pas déjà autre chose de mieux depuis)
    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
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Lorsque tu parles de champs calculés, cela a-t-il un apport avec OnCalcFields ou InternalCalcField
    OnCalcFields étant interne à Delphi
    InternalCalcField indiquant que le champ est issu d'une formule genre "A + B as C" et non directement un champ de la DB

    Comment fais-tu le lien entre ces champs et les procédures stockées, c'est directement dans le SELECT ou tu appels manuellement les procédures stockées dans OnCalcFields
    Le champ est calculé directement au niveau de la base de données:
    dans la structure de la table j'ai deux champs computed by Select(Val_1) from MaProcedureStockee(arg1).

    Au niveau de la query dans delphi, j'ai donc uniquement
    Select MonChampCalculé from ma_table.

    Citation Envoyé par ShaiLeTroll Voir le message
    Le TDBGrid contient des colonnes prédéfinies ou c'est générer à la volée lors de l'ouverture du Query ?
    Les colonnes sont prédéfinies à l'avance.

    Citation Envoyé par ShaiLeTroll Voir le message
    le TIBOQuery contient des champs persistants ou ils sont construit lors du Open ?
    Je ne suis pas tout à fait sûr de comprendre le sens de cette question.
    Je regarderais demain dans les propriétés des champs si je vois quelque chose car j'ai fermé le pc avec delphi et cela fais 1h30 que je devrais déjà être parti :p ce qui fait que je ne le rallumerais pas aujourd'hui.

    Voila comment on fait pour les champs :
    On ecrit la requête dans le composant TIBOQuery
    On double clique sur le composant pour voir la liste des champs.
    Cette liste est vide au départ.
    Clic droit sur la liste ; ajouter les champs ; on les prend tous, puis ok et donc sont crées les champs MaQueryMonChampCalculé1 et MaQueryMonChampCalculé2 .
    Je regarderais demain de plus près à cette notion de champs persistant.

    Citation Envoyé par ShaiLeTroll Voir le message
    TIBOQuery est bien différent du TIBQuery (Interbase Express) qui n'est pas conseillé pour FB dont on recommande l'accès avec UIB (si il n'existe pas déjà autre chose de mieux depuis)
    Oui, il s'agit d'un autre composant.
    voici l'adresse du site officiel des composants que nous utilisons pour se connecter à nos bases de données Firebird: http://www.ibobjects.com/

    Merci pour ta réponse, et bonne soirée.
    Sébastien

  4. #4
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 043
    Points : 40 957
    Points
    40 957
    Billets dans le blog
    62
    Par défaut
    S'il s'agit de champ de type COMPUTED BY , il faut se pencher sur les valeurs= NULL .
    si A ou B = NULL alors C COMPUTED BY (A+B) = NULL
    mais C COMPUTED BY (COALESCE(A,0)+COALESCE(B,0))=0

    - le passage par par paramètre 'corrige' le null surtout s'il y a un parambyname('P').asInteger <- null devient 0
    -il est possible que le 'logiciel style EMS sql manager' fasse la même chose via un COALESCE


    le mieux serait d'avoir le source de la procedure et/ou de la table
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    La table TABLE1 où se trouve les 2 champs calculé à une clef primaire de type integer que je nomme ici ID_INTEGER_TABLE1.

    Voici comment est calculé ces 2 champs calculé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
      POURCENTAGE_1 COMPUTED BY (
      (
        select
          cast(POURCENTAGE_1 as decimal(4, 1))
        from
          CALC_POURCENTAGE_1(MaTable. ID_INTEGER_TABLE1))));
     
     
      POURCENTAGE_2 COMPUTED BY (
      (
        select
          cast(POURCENTAGE_2 as decimal(4, 1))
        from
          CALC_POURCENTAGE_2(MaTable. ID_INTEGER_TABLE1))));

    Voici le code pour créer les 2 procédures stockée dans Firebird qui calculent les 2 pourcentages



    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
    CREATE PROCEDURE CALC_POURCENTAGE_1 (
      ID_INTEGER INTEGER)
    RETURNS(
      POURCENTAGE_1 DECIMAL(18, 1))
    AS
    begin
      select
        case
          when sum(coalesce(PC.EVALUATION_1 * 0, 1)) <> 0 then null  
          else
            cast(
              sum(cast(PC.EVALUATION_SESS_1 * C.COEFFICIENT_IMPORTANCE as double precision))
                / sum(C.COEFFICIENT_IMPORTANCE) as decimal(4, 1))
        end
      from
        TABLE2 PC
        join TABLE3  C on (PC.ID_TABLE3 = C.ID_TABLE3) and (PC. ID_INTEGER_TABLE1 = :IDENTIFIANT)
      where
        C.PRENDRE_EN_COMPTE_CALCUL_POURCENTAGE = 'T'
      into
        : POURCENTAGE_1;
     
      suspend;
    end;



    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
    CREATE PROCEDURE CALC_POURCENTAGE_2 (
      ID_INTEGER INTEGER)
    RETURNS(
      POURCENTAGE_2 DECIMAL(18, 1))
    AS
    begin
      select
        case
          when sum(coalesce(PC.EVALUATION_2 * 0, 1)) <> 0 then null  
          else
            cast(
              sum(cast(PC.EVALUATION_2 * C.COEFFICIENT_IMPORTANCE as double precision))
                / sum(C.COEFFICIENT_IMPORTANCE) as decimal(4, 1))
        end
      from
        TABLE2 PC
        join TABLE3 C on (PC.ID_TABLE3 = C.ID_TABLE3) and (PC. ID_INTEGER_TABLE1 = :IDENTIFIANT)
      where
        C.PRENDRE_EN_COMPTE_CALCUL_POURCENTAGE = 'T'
      into
        : POURCENTAGE_2;
     
      suspend;


    remarque : j'ai ajouter COALESCE(champCalculé2, 0) dans mon composant TIBOQuery et dans la DBGrid liée à ce composant est bien apparu 0 à toute les lignes (alors que la plupart des lignes aurait du avoir une valeur pour le champ calculé2 ... je vois que pour certaine lignes, le champs calculé retourne tout de même null au niveau de la base de donnée, je vais modifier dans une bdd de test les donnée pour que le champs calculé de ces lignes soient toute à 0 pour voir si ce problème est dû à la présence de ligne où le champ calculé est Null.

    Remarque 2 : super utile le coalesce dans Firebird

    Merci pour vos commentaire, je vous tiens au courant de mon avancée pour la résolution de ce problème.

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Bingo, si je remplace :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    when sum(coalesce(PC.EVALUATION_2 * 0, 1)) <> 0 then null
    par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    when sum(coalesce(PC.EVALUATION_2 * 0, 1)) <> 0 then -1
    Je n'ai donc plus aucune ligne où la valeur du champ calculé est à NULL, et là toutes les valeurs calculées de mes lignes s'affichent bien.

    Merci à tous pour vos commentaire,
    Sébastien


    Remarque: j'ai édité le message de départ en mettant [Résolu] au début du titre.. j'ai l'impression qu'il y avait un bouton quelque part pour signaler un message comme étant cloturé ou résolu ... je me trompe?

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 07/12/2014, 20h32
  2. [C#] Problème pour récuperer des données dans une datatgridview
    Par Faible37 dans le forum Débuter
    Réponses: 2
    Dernier message: 22/03/2012, 10h26
  3. Problème synthaxe pour récuperer des liens (HTML)
    Par stansoad0108 dans le forum Langage
    Réponses: 3
    Dernier message: 25/04/2008, 16h37
  4. Problème pour Télécharger des fichiers
    Par joce3000 dans le forum C++Builder
    Réponses: 8
    Dernier message: 21/01/2005, 10h30
  5. problème pour faire des blocs
    Par tinkye_winkye dans le forum Mise en page CSS
    Réponses: 6
    Dernier message: 04/01/2005, 14h13

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