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 :

FireBird 2.5 - TIBSQL : pb de reqoête


Sujet :

Bases de données Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 942
    Par défaut FireBird 2.5 - TIBSQL : pb de reqoête
    Bonjour,

    Malgrès que mon code soit du C++, je poste ici car il me semble que le problème vient du fait que mon utilisation du TIBSQL est incorrecte ( le forum Builder C++ ne semble pas être très fréquenté ).

    Avec XE4, je suis en train de reprendre un vieux programme écrit à l'origine avec Builder 6, j'ai un problème avec une méthode qui permet de modifier le montant HT des consos lorsque le taux de TVA change.

    Il y a une exception EIBClientError avec le message field CO_PRIXDEVENTETTC not found, j'ai vérifié, le champ éxiste bien dans la table, voici le code :

    Le code est du C++ mais je ne pense pas qu'il soit incompréhensible pour les delphistes

    Code c++ : 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
    ...
      TIBSQL *IBSQL;
    ...
    
    void __fastcall TDMFactu::ModifTVAConsos(int P_iCodeTVA, double P_dTauxTVA)
    {
    	String  l_sSQL;
    
            if (!IBQConsos->Active)
    		IBQConsos->Active = True;
    	IBSQL->SQL->Clear();
    	if(!IBTransaction->InTransaction)
    		IBTransaction->StartTransaction();
    	try
    	{
    		l_sSQL = "UPDATE CONSO ";
    		l_sSQL += "SET CO_CODETVA = '" + String(P_iCodeTVA) + "',";
    		l_sSQL += " CO_TAUXTVA = :RESULT1,";
    		l_sSQL += " CO_PRIXDEVENTEHT = :RESULT2";
    		l_sSQL += " WHERE CO_CODETVA = '" + String(P_iCodeTVA) + "'";
    		IBSQL->SQL->Add(l_sSQL);
    		IBSQL->ParamByName("RESULT1")->AsFloat = P_dTauxTVA;
    		IBSQL->ParamByName("RESULT2")->AsFloat = IBSQL->FieldByName("CO_PRIXDEVENTETTC")->Value / (1 + (P_dTauxTVA / 100)); // <- Erreur ICI champ CO_PRIXDEVENTETTC inconnu
    		IBSQL->ExecQuery();
    		IBTransaction->Commit(); // Fin de la transaction.
    	}
    	catch(...)
    	{
    		if(IBTransaction->InTransaction)
    			IBTransaction->Rollback();
    	}
    	IBQConsos->Close();
    }

    Il n'est pas possible de faire un update comme ci-dessus ?

    Merci d'avance

  2. #2
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 680
    Billets dans le blog
    65
    Par défaut
    Bonjour,

    avant tout quelques remarques :
    cette mise à jour ne serait-elle pas mieux dans un trigger AFTERUPDATE sur la table TVA ?
    au niveau de la structure de la table sensu stricto il n'est jamais bon de mettre un champ de ce type, c'est à dire qui peut se calculer, il aurait été mieux de stocker le code TVA et une jonction CONSO table TVA aurait fait le boulot grâce à un SQL

    pour ce qui est du SQL du code
    a'
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE CONSO SET CO_CODETVA='+QUotedStr(P_iCodeTVA)+',CO_TAUXTVA = :RESULT1,CO_PRIXDEVENTEHT = :RESULT2 WHERE CO_CODETVA ='+QuotedStr(P_IcodeTVA)
    on s'embrouille entre les " et si c++ à la fonction quotedstr autant l'utiliser
    a) tu n'es pas allé jusqu'au bout de ta démarche pour les paramètres ce qui aurait été mieux
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE CONSO SET CO_CODETVA=:CODE,CO_TAUXTVA = :RESULT1,CO_PRIXDEVENTEHT = :RESULT2 WHERE CO_CODETVA =:CODE
    b) pas la peine de mettre à jour le champ que tu met en recherche WHERE
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE CONSO SET CO_TAUXTVA = :RESULT1,CO_PRIXDEVENTEHT = :RESULT2 WHERE CO_CODETVA =:CODE

    enfin concernant l'erreur, lorsque je lis ce dernier SQL j'en déduit que que le TAUX de TVA doit être stocké dans la table CONSO il est donc fort probable que CO_PRIXDEVENTEHT soit un champ calculé (COMPUTED BY) et un champ calculé ne peut pas être modifié par SQL d'où l'erreur
    et la réponse à ta question :
    Il n'est pas possible de faire un update comme ci-dessus ?

  3. #3
    Membre émérite
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 942
    Par défaut
    Bonjour,

    Merci pour ces remarques


    Citation Envoyé par SergioMaster Voir le message
    au niveau de la structure de la table sensu stricto il n'est jamais bon de mettre un champ de ce type, c'est à dire qui peut se calculer, il aurait été mieux de stocker le code TVA et une jonction CONSO table TVA aurait fait le boulot grâce à un SQL
    Je ne suis pas sur que cela soit une bonne solution

    Citation Envoyé par SergioMaster Voir le message
    on s'embrouille entre les " et si c++ à la fonction quotedstr autant l'utiliser
    Oui, c'est vrai et elle éxiste aussi pour C++ mais à l'époque je ne connaissais pas QuotedStr ( ou cela n'éxistait pas encore )

    Citation Envoyé par SergioMaster Voir le message
    a) tu n'es pas allé jusqu'au bout de ta démarche pour les paramètres ce qui aurait été mieux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE CONSO SET CO_CODETVA=:CODE,CO_TAUXTVA = :RESULT1,CO_PRIXDEVENTEHT = :RESULT2 WHERE CO_CODETVA =:CODE'
    b) pas la peine de mettre à jour le champ que tu met en recherche WHERE
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE CONSO SET CO_TAUXTVA = :RESULT1,CO_PRIXDEVENTEHT = :RESULT2 WHERE CO_CODETVA =:CODE'
    Oui, tu as raison, je vais le modifier.

    Citation Envoyé par SergioMaster Voir le message
    enfin concernant l'erreur, lorsque je lis ce dernier SQL j'en déduit que que le TAUX de TVA doit être stocké dans la table CONSO il est donc fort probable que CO_PRIXDEVENTEHT soit un champ calculé (COMPUTED BY) et un champ calculé ne peut pas être modifié par SQL d'où l'erreur
    et la réponse à ta question :
    Non, ce n'est pas un champ calculé et je ne comprends pas pourquoi cela ne fonctionne pas.

    Citation Envoyé par SergioMaster Voir le message
    Bonjour,

    cette mise à jour ne serait-elle pas mieux dans un trigger AFTERUPDATE sur la table TVA ?
    C'est effectivement une solution.

  4. #4
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 680
    Billets dans le blog
    65
    Par défaut
    Bonjour,
    Citation Envoyé par sergiomaster
    il aurait été mieux de stocker le code TVA et une jonction CONSO table TVA aurait fait le boulot grâce à un SQL
    Citation Envoyé par free07 Voir le message
    Je ne suis pas sur que cela soit une bonne solution
    pourtant c'est la plus "normalisée" . Ne pas stocker le taux TVA, ni d'ailleurs le PrixTTC et utiliser une vue pour obtenir ces deux derniers éviterait carrément d'avoir à faire ce traitement.
    S'il s'agissait par contre d'un historique (factures à garder, etc..) par contre effectivement le taux serait stocké (pour par exemple des rééditions) et le champ PrixTTC pourrait même être un champ calculé.

    Je ne suis pas un gourou SQL mais je pense que c'est le bon choix

    [Edit] maintenant que j'y regarde de plus près je suis parti du postulat que le PrixTTC était le champ à calculer et le prixHT le champ de base or je m’aperçois qu'il s'agit du contraire et du coup je comprends mieux l'erreur !
    un ExecSQL (UPDATE,INSERT,DELETE) ne va pas chercher de données et donc ton IBSQL->FieldByName("CO_PRIXDEVENTETTC")->Value ne peut être obtenu
    au pire, la solution du trigger restant la mieux, tu peux faire la chose suivante

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE CONSO SET CO_TAUXTVA = :RESULT1,CO_PRIXDEVENTEHT =CO_PRIXDEVENTETTC/ (1 + (:RESULT1 / 100))  WHERE CO_CODETVA =:CODE
    plus d'erreur de champ inconnu
    Mais là, attention tu vas obtenir un résultat avec beaucoup trop de décimales (Firebird oblige)
    exemples :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    select 18.50/100,17.756/100.00,19.80/100.00,20.5/100.0000 from RDB$DATABASE
    donne
    0.18,0.17756,0.1980,0.20500
    donc déjà, l'intérêt de bien "caster" ou arrondir et la nécessité de bien connaitre ton type de champ
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select 118.65/(1+(18.65/100.00)) AS TVASANSARRONDI,
    CAST(118.65/(1+(18.65/100.00)) AS NUMERIC(15,2)) AS TVAAVECCAST
    from RDB$DATABASE
    là tu me diras les deux sont égaux (évidemment mais j'ai aussi pris un chiffre rond comme résultat ) et pas tout à fait si tu fais attention aux chiffres après la virgule
    100.000000,100.00
    en mettant maintenant une valeur TTC de 100
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select 100.00/(1+(18.65/100.00)) AS TVASANSARRONDI,
    CAST(100.00/(1+(18.65/100.00)) AS NUMERIC(15,2)) AS TVAAVECCAST
    from RDB$DATABASE
    on commence à apercevoir le problème
    84.281500,84.28
    d'un coté on a la "vraie bonne" valeur de l'autre, avec le cast, on perd 0.0015
    en repassant dans l'autre sens HT->TTC (sur une calculette) on obtient
    99.999999999, 99.99822
    tu rétorqueras que c'est une broutille mais bon j'ai déjà eu affaires à des comptables pointilleux et un écart de 1cent pour eux, c'est une catastrophe

    Bref, cette démonstration est faite pour te démontrer quelques subtilités/pièges à éviter pour ta formulation SQL
    N.B. c'est également vrai pour l'établissement du trigger

    Suggestion voir les fonctions interne CAST,ROUND,TRUNC

  5. #5
    Membre émérite
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 942
    Par défaut
    Non, je ne dirais pas que c'est une broutillle, j'ai été sensiblilisé à ce problème de précision et je sauvegarde tous les opérateurs avec 4 chiffres après la virgule, je pense que c'est suffisant, non ?

    Sinon, pour cette histoire de trigger, il faut aussi que je gère la transaction au cas ou la modif du montant HT échoue, que le nouveau montant de la TVA ne change pas non plus.

    Je vais m'orienter plutôt vers les bonnes pratiques SQL et mettre une relation entre la table des consos et la TVA par le code TVA et utiliser une jointure.

    Finalement je ne vois aucune raison pour garder le taux de TVA dans la table des consos, je garde les montants dans la table de factures mais c'est pour avoir un historique ( comme tu l'as précisé ).

    Merci pour ton aide.

    EDIT : En fait, il est inutilie que je mémorise les montant HT dans la table des conso

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

Discussions similaires

  1. Firebird 2.5 - TIBSQL: pb de requête update
    Par free07 dans le forum C++Builder
    Réponses: 0
    Dernier message: 29/09/2015, 12h02
  2. [Débat] Choisir InterBase/Firebird ou Microsoft SQL-SERVER ?
    Par asenaici dans le forum Décisions SGBD
    Réponses: 90
    Dernier message: 19/03/2009, 20h51
  3. [FIREBIRD]Drivers ODBC
    Par tripper.dim dans le forum Connexion aux bases de données
    Réponses: 10
    Dernier message: 24/04/2007, 11h02
  4. [firebird] Connexion impossible en lecture seule
    Par severine dans le forum Administration
    Réponses: 2
    Dernier message: 01/08/2003, 15h35
  5. Refus d'accès à une base Firebird
    Par severine dans le forum Installation
    Réponses: 18
    Dernier message: 04/06/2003, 16h03

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