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 :

insert DBGrid avec TADOQuery et requete avec jointure


Sujet :

Bases de données Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Ingenieur developpement
    Inscrit en
    Septembre 2002
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 56
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Ingenieur developpement

    Informations forums :
    Inscription : Septembre 2002
    Messages : 175
    Par défaut insert DBGrid avec TADOQuery et requete avec jointure
    Bonjour,

    J'ai un TAdoQuery avec une requete avec jointure.

    La tentative d'insertion échoue.
    Je peux prendre la mise à jour sur le beforePost et mettre à jour moi même les tables concernées et faire un Dataset.Cancel ou un Abort, mais même si je fais un Dataset.Refresh à la fin du BeforePost, la grille ne se met pas à jour.

    Quelle est la meilleure démarche afin d'insérer des données à partir d'une grille liée à une requête avec jointure ?
    Quel événement utiliser? Comment mettre à jour afin que cela soit transparent pour l'utilisateur ?

    Je sais que ADO se débrouille pas mal pour faire l'update sur une requete jointe en envoyant plusieurs update dans les tables qui vont biens.

    Merci de vos conseils

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 086
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 086
    Par défaut
    Quel est le message d'erreur si il y en a un ?
    As-tu fournis dans la jointure toutes les clés primaires de chacune des tables ?
    Je ne pratique que très rarement la saisie directement dans les grilles car cela manque de confort pour la saisie en masse de donnée tout au clavier
    Lors que je l'ai fait, j'ai utilisé un TClientDataSet sur des MKQuery, ou via le TSimpleDataSet de DBExpress, les deux utilisant un cache qui me permettait de générer moi même les requêtes dans le BeforeApplyUpdates ou manuellement par l'échange du Data sous forme de Variant entre une DLL IHM et une DLL Métier

    Je ne comprend pas pourquoi en ADO ou DBExpress, il n'y existe pas un équivalent de TUpdateSQL qui permettait de définir précisément les requêtes surtout si la jointure récupère par exemple 3 tables et que l'on souhaite qu'en mettre qu'une ou deux à jour !
    Si quelqu'un connait la bonne pratique cela m'intéresse !
    Personnellement, j'ai abandonné, depuis 2004, le Insert()\Post() direct au profil de SQL généré à la volée par une couche d'objet persistant !
    Cela permet de maîtriser chaque requête SQL qui sont émises par le programme !
    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
    Ingenieur developpement
    Inscrit en
    Septembre 2002
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 56
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Ingenieur developpement

    Informations forums :
    Inscription : Septembre 2002
    Messages : 175
    Par défaut
    Voici le message d'erreur si je le laisse faire, ce qui est bien compréhensible car il ne sais pas ce que je dois faire.

    Impossible d'insérer la valeur null dans la colonne 'N_IDGAMME', table GAMMEMERE. Cette colonne n'accepte pas les valeurs NULL. Echec de INSERT
    Mon but est de faire comme dans le BeforeApplyUpdate mais avec les ADO.

    Dans mon exemple, j'ai 2 tables (.
    Une table GAMME avec IdGamme et LibGamme
    Une autre GAMMEMERE avec IdGamme, IdGammeMere et Ordre (Les 2 Id étant des FK de Gamme).
    Une gamme mère contient des gammes dans un ordre précisé.

    La requete étant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    select 
      GAMME.IdGamme,
      GAMME.LibGamme,  
      GAMMEMERE.ORDRE, 
      GAMMEMERE.idGAMMEMERE
    from GAMME
      join GAMMEMERE on GAMME.IDGAMME = GAMMEMERE.IDGAMME
    where GAMMEMERE.idGAMMEMERE = :Gamme
    order by ORDRE
    Mon but étant d'insérer des gammes pour la gamme mère passée en paramètre et donc 2 insert dans l'ordre gamme, gammemere.
    Dans événement NewRecord ou BeforePost, je met à jour le IdGammeMere.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    insert into gamme (LibGamme) values (AdoQLibGamme.Value)
    Récupérer Id de la séquence
    insert into gammeMere (IdGammeMere, IdGamme, ordre) values (AdoQIdGammeMere.Value, Id recup, ordre)
    Ce qu'il essai de faire
    insert into gamme (LibGamme) values (AdoQLibGamme.Value)
    insert into gammeMere (IdGammeMere, IdGamme, ordre) values (AdoQIdGammeMere.Value, NULL, ordre)
    ADO ne récupère pas l'Id pour le mettre dans l'insertion suivante.

    Je peux faire les insertions dans le beforePost mais il faut que j'annule les modification qu'il s’apprête à faire par un Dataset.Cancel et un Abort pour sortir. La grille se remet comme avant la saisie et ne reflète plus les modifications apportées dans la base.

    PS : la dbGrid est une QuantumGrid

  4. #4
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 086
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 086
    Par défaut
    Je crois qu'il n'y arrive jamais !
    Comment veux-tu qu'il devine que tu veux utiliser la valeur du dernirer AutoInc de GAMME pour l'utiliser comme valeur pour GAMMEMERE !
    Certe les noms de champ sont les mêmes mais cela supposerait de la couche ADO une analyse de ton modèle de donnée, faut pas abuser !

    En plus, tu ne fournis pas "GAMMEMERE.IDGAMME" dans le SELECT, pour lui ce champ ne peut pas avoir de Valeur !
    Essaye de voir si en ajoutant ce champ dans le SELECT, ADO fasse un miracle, je n'y crois pas trop !

    Perso, je n'ai jamais fait confiance au mise à jour automatique de jointure !
    J'évite ce type de procédé, déjà que l'IDE cela rend flémard les développeurs mais là !
    De toute façon, c'est contraire une architecture MVC et une conception POO avec une couche Metier !

    A mon avis tu ne peux que le faire manuellement car il te faut intercepter la valeur entre deux requêtes !
    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
    Membre confirmé
    Profil pro
    Ingenieur developpement
    Inscrit en
    Septembre 2002
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 56
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Ingenieur developpement

    Informations forums :
    Inscription : Septembre 2002
    Messages : 175
    Par défaut
    Le fait de rajouter l'IdGamme de la GammeMere ne change rien.

    Il y a une intelligence dans l'ADO qui permet de mettre à jour plusieurs tables par l'envoi de plusieurs requêtes.
    Exemple de l'update (Code généré par l'ADO intercepté par profiler).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    UPDATE "GAMME" SET "LIBGAMME"=@P1 WHERE "IdGamme"=@P2 AND "LIBGAMME"=@P3
    UPDATE "GAMMEMERE" SET "ORDRE"=@P1 WHERE "IdGamme"=@P2 AND "ORDRE"=@P3 AND "idGAMMEMERE"=@P4
    Ce lien montre l'utilisation un peu plus poussée de ADO
    Working with ADO

    Je suis d'accord avec toi qu'il ne faut pas trop lui en demander et c'est pourquoi je met à jour la base dans l'événement BeforePost et fais un Dataset.Cancel puis je réactualise avec Close, Open.
    C'est pas Top mais çà fonctionne.
    C'est surtout pour savoir si d'autre personnes font différemment. Depuis le temps que çà existe, d'autres personnes ont dû résoudre le problème. Toute suggestion est bonne à prendre

    Merci pour tes réponses.

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 086
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 086
    Par défaut
    Ta méthode est un classique, je pense l'avoir fait plusieurs fois lors que j'ai maitenu des écrans existants !
    Sinon, j'utilisais massivement le TClientDataSet, pour présenter les données dans une TDBCtrlGrid ou TDBGrid pour l'utilisateur alors que le stockage était différent (DB orientée colonnes et non par ligne à cause d'une structure polymorphe des enregistrements !)

    Donc en utilisant TClientDataSet, tu as les données en mémoire, tu peux faire le Post() sans devoir faire un Refresh !
    Et tu gères le SQL à la main !
    Pour utiliser le TClientDataSet, tu as aussi ajouté un TDataSetProvider relié sur le ADOQuery !
    Dans TDataSetProvider.BeforeUpdateRecord, tu peux capturer l'envoie du Post, le faire toi même en SQL, en affectant true à Applied, cela considère que le Post a été effectué !

    C'est une méthode propre et classique de l'utilisation d'un cache !
    Le problème c'est que cela consomme plus de mémoire à l'ouverture de la Query et que c'est plus lent puisque cela copie les enregistrements dans le cache !
    Mais bon, cela reste supportable, surtout avec les machines que l'on a maintenant !
    Et puis, tu ne dois pas avoir un volume de données importants < 1000 !

    Tu noteras quand même que les requêtes d'ADO ne sont pas terrible non ?
    les WHERE des UPDATE utilisent TOUS Les champs du Select, alors qu'il suffit de IdGamme pour GAMME et idGAMMEMERE+IdGamme pour GAMMEMERE
    Si tu as 20 champs, va-t-il pondre un WHERE de 20 champs alors qu'il a les clés primaires uniques ?
    Je n'ai pas assez utilisé ADO pour le savoir mais je le crainds car je l'ai vu dans d'autres lib DB !

    Dans le genre "intelligence", cela reste faible, aucune analyse réel du modèle, juste, un algo qui reprend tous les champs en présence de chacune des tables !
    C'est d'ailleurs pour cela que cela fasse des erreurs genre "Erreur de mise à jour en plusieurs étapes" parce que le WHERE a renvoyé plusieurs enregistrements ou même parfois aucun, car un autre client concurrent à déjà modifier les valeurs !
    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

Discussions similaires

  1. TADOQuery et requete avec fonction CONCAT et/ou LEFT
    Par dnode57 dans le forum Bases de données
    Réponses: 3
    Dernier message: 29/07/2009, 15h55
  2. Réponses: 2
    Dernier message: 04/06/2009, 13h36
  3. Double requete avec _GET mais pas avec _POST
    Par rickilami dans le forum Langage
    Réponses: 2
    Dernier message: 17/11/2008, 16h03
  4. requete avec 2 jointures
    Par bissy88 dans le forum Langage SQL
    Réponses: 4
    Dernier message: 30/04/2004, 13h52
  5. Requete avec une sous-requete... Ne fonctionne qu'a moitie..
    Par mythtvtalk.com dans le forum MS SQL Server
    Réponses: 10
    Dernier message: 18/08/2003, 09h54

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