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

 Firebird Discussion :

Comment mettre à jour deux tables ensemble?


Sujet :

Firebird

  1. #1
    Nouveau membre du Club
    Comment mettre à jour deux tables ensemble?
    salut a tous


    Je veux mettre à jour dans deux tables mais la requête n'a pas fonctionné où se trouve l'erreur.
    J'utilise FIREBIRD 3 et Firedac

    Code Delphi :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Dmdata.qryUpdate.SQL.Text:='update employeur E ,Fonctions F set E.Nom=:Nom,E.Prenom=: Prenom,E.DateNaissance=: DateNaissance,F.NomFonction=:NomFonction where id= '+QuotedStr(DBEditID.Text)+' ';
              Dmdata.qryUpdate.Params.ParamByName('Nom').AsString:= DBEdit1.Text;
              Dmdata.qryUpdate.Params.ParamByName('Prenom').AsString:= DBEdit2.Text;
              Dmdata.qryUpdate.Params.ParamByName('DateNaissance').AsString:= DBEdit3.Text;
              Dmdata.qryUpdate.Params.ParamByName('NomFonction').AsString:= DBEdit4.text;
              Dmdata.qryUpdate.ExecSQL;
    end;

  2. #2
    Rédacteur/Modérateur

    Bonjour,

    Tout d'abord je dirais que ce n'est pas vraiment un problème Firebird mais Delphi.
    Je ne crois pas même qu'un update de deux tables soit dans la norme SQL, en tout cas ce n'est pas dans la syntaxe de UPDATE de Firebird.

    Côté Firedac, et donc Delphi, par contre je n'ai jamais essayé de mettre deux UPDATE au sein d'une même FDQuery. Je sais qu'il est possible de mettre plusieurs SELECT mais j'avoue que je suis déjà frileux quant à utiliser cette possibilité, alors deux UPDATE

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    Update employeur E ,Fonctions F set E.Nom=:Nom,E.Prenom=: Prenom,E.DateNaissance=: DateNaissance,F.NomFonction=:NomFonction where id= '+QuotedStr(DBEditID.Text)

    Que c'est moche : - une jointure devrait s'écrire proprement (JOIN ... ON...) .
    - vous utilisez des paramêtres pour les valeurs mais pas pour la clause WHERE
    - Vos zones de saisie ont des noms non explicite
    Y-a t-il une quelconque relation entre les deux tables ? Je présume/espére que oui, du genre E.IDFONCTION=F.IDFONCTION avec la contrainte (FOREIGN KEY) adaptée, à moins que ce soit E.ID=F.ID

    A lire ce que vous avez codé, je crains quand même que la structure des tables ne soit que très approximative !
    une ID chaine, certainement une clé primaire
    une dateNaissance sous forme de chaine (pour moi ça c'est le pire)
    une relation non explicite entre la Table Employeur et la table Fonction


    Plusieurs solutions s'offrent quand même,
    Côté Firebird : écrire une procédure avec paramètres
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    CREATE PROCEDURE UPDATE_EMPFONC
    (ID  VARCHAR(),
     NOM VARCHAR(),
     PRENOM VARCHAR(),
     DN VARCHAR(),
     FONCTION VARCHAR() 
    ) 
    AS BEGIN
    UPDATE EMPLOYEUR Employeur Set Nom=:NOM,Prenom=<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />RENOM,DateNaissance=<img src="images/smilies/icon_biggrin.gif" border="0" alt="" title=":D" class="inlineimg" />N WHERE id=:ID;
    UPDATE FONCTION SET NOMFONCTION=:FONCTION WHERE ......;
    END


    Côté Delphi :
    - simplement écrire deux SQL.
    Avec Firedac, même pas besoin d'utiliser 2 FDQuerys, utiliser la syntaxe de FDConnexion
    Code Delphi :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Dmdata.FDConnexion1.ExecSQL('UPDATE Employeur Set Nom=?,Prenom=?,DateNaissance=? WHERE id=?',
                                               [ DBEdit1.Text,
                                                  DBEdit2.Text,
                                                  DBEdit3.Text,
                                                  DBEditID.Text]);

    Je serai bien en peine d'écrire le second SQL faute de connaitre la relation ! mais, au pire
    Code Delphi :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    Dmdata.FDConnexion1.ExecSQL('UPDATE FONCTION Set NomFonction=? WHERE nomFonction=?',
                                                                  [DBEdit4.text, DBEdit4.text]);
    //NB, il y a peut être même une syntaxe permettant de ne pas avoir à doubler DBEdit4.text


    - Utiliser un FDScript contenant les deux SQL
    La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein

    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Tokyo, Rio, Sidney) et peut être quelques autres
    SGBD : Firebird 2.5, 3, SQLite
    générateurs Etats : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Ubuntu, Androïd

  3. #3
    Nouveau membre du Club
    Citation Envoyé par SergioMaster Voir le message
    Bonjour,

    - une jointure devrait s'écrire proprement (JOIN ... ON...) .


    oui il y a une relation entre les deux tables
    Employeur(ID,FoncID,Nom,Prenom,DateNaissance)
    Fonctions(FoncID,NomFonction)

    C'est la première fois que je connais . FDConnexion1.ExecSQL .Je l'ai essayé et ça marche efficacement.
    merci beaucoup SergioMaster

  4. #4
    Rédacteur/Modérateur

    Bonjour,

    Quelques petites choses à ajouter alors

    1- j'ai utiliser des paramètres "anonymes" dans mes SQL ce n'est pas conseillé sauf pour compatibilité DataSnap
    Le symbole '?' est reconnu en tant que marqueur de paramètre sans nom. Utilisé dans le cadre de la compatibilité avec DataSnap, il ne doit pas être utilisé dans une application FireDAC classique.
    2- au sein d'un FDQuery on peut effectivement mettre plusieurs SQL (ne pas oublier le ; en fin de chaque requête) à partir du moment où les paramètres seront nommés il n'y a pas de difficulté
    ici, une Query créée au runtime
    Code Delphi :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
    var AQuery : TFDQuery;
    begin
    Aquery:=TFDQuery.Create(Self);
    try
      AQuery.Connection:=Dmdata.FDConnexion1;
      AQuery.SQL.Add('UPDATE EMPLOYEUR Set Nom=:NOM,Prenom=<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />RENOM,DateNaissance=<img src="images/smilies/icon_biggrin.gif" border="0" alt="" title=":D" class="inlineimg" />N WHERE id=:ID;')
      AQuery.SQL.Add('UPDATE UPDATE FONCTION SET NOMFONCTION=:FONCTION WHERE FONCID=(SELECT FONCID FROM EMPLOYEUR WHERE id=:ID);');
      AQuery.ParamBYName('NOM').asString:=DBEdit1.Text;
      AQuery.ParamBYName('PRENOM').asString:=DBEdit2.Text;
      AQuery.ParamBYName('DN').asString:=DBEdit3.Text;
      AQuery.ParamBYName('ID').asString:=DBEditID.Text;
      AQuery.ParamBYName('FONCTION').asString:=DBEdit4.Text;
      AQuery.ExecSQL;
    finally
      FreeAndNil(AQuery);
    end;


    3- En théorie, il serait possible de le faire avec FDConnection.ExecSQL, avec les SQL exposés en 2

    4- Avec MySQL il est possible d'indiquer des valeurs récupérées par @mavaleur (cf les réponses d'AndNotOr), peut-être, puisqu'il y a la possiblité d'utiliser RETURNING est-il possible dans le premier SQL de récupérér FONCID
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    UPDATE EMPLOYEUR Set Nom=:NOM,Prenom=<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />RENOM,DateNaissance=<img src="images/smilies/icon_biggrin.gif" border="0" alt="" title=":D" class="inlineimg" />N WHERE id=:ID RETURNING FONCID INTO :IDF

    Peut-être que le préprocesseur de Firedac permettrait de mettre la colonne retournée dans un paramètre (voir ici la première syntaxe)
    Code Delphi :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
      AQuery.SQL.Add('UPDATE EMPLOYEUR Set Nom=:NOM,Prenom=<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />RENOM,DateNaissance=<img src="images/smilies/icon_biggrin.gif" border="0" alt="" title=":D" class="inlineimg" />N WHERE id=:ID RETURNING FONCID  {INTO :IDF};')
      AQuery.SQL.Add('UPDATE UPDATE FONCTION SET NOMFONCTION=:FONCTION WHERE FONCID=:IDF;'


    Cela fait au moins une théorie (point 3) et deux peut-êtres (point 4) donc AMHA à éviter sans vérifications
    Cela s'appuie sur les possiblités de Firedac et non sur le SQL de Firebird , d'où ma remarque
    Citation Envoyé par SergioMaster
    Tout d'abord je dirais que ce n'est pas vraiment un problème Firebird mais Delphi.
    et il faut bien comprendre que le préprocesseur de Firedac va en fait faire les deux requêtes pas une seule
    La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein

    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Tokyo, Rio, Sidney) et peut être quelques autres
    SGBD : Firebird 2.5, 3, SQLite
    générateurs Etats : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Ubuntu, Androïd

  5. #5
    Nouveau membre du Club
    Merci beaucoup
    J'ai appris beaucoup d'idées de vous, Professeur SergioMaster

###raw>template_hook.ano_emploi###