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 :

[Firedac] FDConnection.ExecSQL et paramètres


Sujet :

Bases de données Delphi

  1. #1
    Rédacteur/Modérateur

    [Firedac] FDConnection.ExecSQL et paramètres
    Bonjour,

    j'utilise souvent ce genre de code
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    FDConnection.ExecSQL('UPDATE EXPEDITION_ENTETE SET ETAT=3 WHERE NUMERO=?',[NBL]);


    Je me trouve confronté à un SQL de ce genre et donc une question pour Expert Firedac
    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
     
    // syntaxe non vérifiée
    SQLUPDTLCMDCLI='UPDATE LCMDCLI SET '+
                    'QTELIV1=IIF(QTELIV1+:Q1>QTECDE1,QTECDE1,QTELIV1+:Q1),'+
                    'QTELIV2=IIF(QTELIV2+:Q2>QTECDE2,QTECDE2,QTELIV2+:Q2),'+
                    'QTELIV3=IIF(QTELIV3+:Q3>QTECDE3,QTECDE3,QTELIV3+:Q3),'+
                    'QTELIV4=IIF(QTELIV4+:Q4>QTECDE4,QTECDE4,QTELIV4+:Q4),'+
                    'QTELIV5=IIF(QTELIV5+:Q5>QTECDE5,QTECDE5,QTELIV5+:Q5),'+
                    'QTELIV6=IIF(QTELIV6+:Q6>QTECDE6,QTECDE6,QTELIV6+:Q6),'+
                    'QTELIV7=IIF(QTELIV7+:Q7>QTECDE7,QTECDE7,QTELIV7+:Q7),'+
                    'QTELIV8=IIF(QTELIV8+:Q8>QTECDE8,QTECDE8,QTELIV8+:Q8),'+
                    'QTELIV9=IIF(QTELIV9+:Q9>QTECDE9,QTECDE9,QTELIV9+:Q9),'+
                    'QTELIV10=IIF(QTELIV10+:Q10>QTECDE10,QTECDE10,QTELIV10+:Q10),'+
                    'QTELIV11=IIF(QTELIV11+:Q11>QTECDE11,QTECDE11,QTELIV11+:Q11),'+
                    'QTELIV12=IIF(QTELIV12+:Q12>QTECDE12,QTECDE12,QTELIV12+:Q12),'+
                    'QTELIV13=IIF(QTELIV13+:Q13>QTECDE13,QTECDE13,QTELIV13+:Q13),'+
                    'QTELIV14=IIF(QTELIV14+:Q14>QTECDE14,QTECDE14,QTELIV14+:Q14),'+
                    'QTELIV15=IIF(QTELIV15+:Q15>QTECDE15,QTECDE15,QTELIV15+:Q15),'+
                    'QTELIV16=IIF(QTELIV16+:Q16>QTECDE16,QTECDE16,QTELIV16+:Q16),'+
                    'QTELIV17=IIF(QTELIV17+:Q17>QTECDE17,QTECDE17,QTELIV17+:Q17),'+
                    'QTELIV18=IIF(QTELIV18+:Q18>QTECDE18,QTECDE18,QTELIV18+:Q18),'+
                    'QTELIV19=IIF(QTELIV19+:Q19>QTECDE19,QTECDE19,QTELIV19+:Q19),'+
                    'QTELIV20=IIF(QTELIV20+:Q20>QTECDE20,QTECDE20,QTELIV20+:Q20),'+
                    'QTELIV21=IIF(QTELIV21+:Q21>QTECDE21,QTECDE21,QTELIV21+:Q21),'+
                    'QTELIV22=IIF(QTELIV22+:Q22>QTECDE22,QTECDE22,QTELIV22+:Q22),'+
                    'QTELIV23=IIF(QTELIV23+:Q23>QTECDE23,QTECDE23,QTELIV23+:Q23),'+
                    'QTELIV24=IIF(QTELIV24+:Q24>QTECDE24,QTECDE24,QTELIV24+:Q24) '+
                    'WHERE SAISON_CMDE=:SC AND NUM_CMDE=NC AND LIGNE=:L';

    Qui m'oblige donc à doubler pas mal de paramètres
    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
         ConnexionUS.ExecSQL(SQLUPDTLCMDCLI,
                               [Q.FieldbyName('Q1').asInteger,Q.FieldbyName('Q1').AsInteger,
                                Q.FieldbyName('Q2').asInteger,Q.FieldbyName('Q2').AsInteger,
                                Q.FieldbyName('Q3').asInteger,Q.FieldbyName('Q3').AsInteger,
                                Q.FieldbyName('Q4').asInteger,Q.FieldbyName('Q4').AsInteger,
                                Q.FieldbyName('Q5').asInteger,Q.FieldbyName('Q5').AsInteger,
                                Q.FieldbyName('Q6').asInteger,Q.FieldbyName('Q6').AsInteger,
                                Q.FieldbyName('Q7').asInteger,Q.FieldbyName('Q7').AsInteger,
                                Q.FieldbyName('Q8').asInteger,Q.FieldbyName('Q8').AsInteger,
                                Q.FieldbyName('Q9').asInteger,Q.FieldbyName('Q9').AsInteger,
                                Q.FieldbyName('Q10').asInteger,Q.FieldbyName('Q10').AsInteger,
                                Q.FieldbyName('Q11').asInteger,Q.FieldbyName('Q11').AsInteger,
                                Q.FieldbyName('Q12').asInteger,Q.FieldbyName('Q12').AsInteger,
                                Q.FieldbyName('Q13').asInteger,Q.FieldbyName('Q13').AsInteger,
                                Q.FieldbyName('Q14').asInteger,Q.FieldbyName('Q14').AsInteger,
                                Q.FieldbyName('Q15').asInteger,Q.FieldbyName('Q15').AsInteger,
                                Q.FieldbyName('Q16').asInteger,Q.FieldbyName('Q16').AsInteger,
                                Q.FieldbyName('Q17').asInteger,Q.FieldbyName('Q17').AsInteger,
                                Q.FieldbyName('Q18').asInteger,Q.FieldbyName('Q18').AsInteger,
                                Q.FieldbyName('Q19').asInteger,Q.FieldbyName('Q19').AsInteger,
                                Q.FieldbyName('Q20').asInteger,Q.FieldbyName('Q20').AsInteger,
                                Q.FieldbyName('Q21').asInteger,Q.FieldbyName('Q21').AsInteger,
                                Q.FieldbyName('Q22').asInteger,Q.FieldbyName('Q22').AsInteger,
                                Q.FieldbyName('Q23').asInteger,Q.FieldbyName('Q23').AsInteger,
                                Q.FieldbyName('Q24').asInteger,Q.FieldbyName('Q24').AsInteger,
                                Q.FieldbyName('SAISON_CMDE').asString,
                                Q.FieldbyName('NUM_CMDE').asInteger,
                                Q.FieldbyName('LIGNE').asInteger
                                ]);

    Je me demandais s'il n'y avait pas une syntaxe qui me permettrait d'éviter le dédoublement genre [Q1=Q.FieldbyName('Q1').asInteger,Q2=Q.FieldbyName('Q2').asInteger, ....]
    Je n'ai pas encore épluché ma Bible (Delphi in Depth : Firedac) et j'avoue le cas est un peu tiré par les cheveux. Il me semble avoir lu quelque part ce genre de syntaxe mais si un connaisseur Firedac a déjà la réponse merci.

    Bien sûr j'envisage d'autres solutions peut-être moins brutales avec un FDQuery avec son ParamByname je n'aurais pas ce "doublement"
    toutefois, il y a souvent plusieurs lignes à modifier, j'envisage donc aussi un ArrayDML du coup cela reste du même accabit
    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

  2. #2
    Rédacteur/Modérateur

    TFDConnection traite les paramètres par nom et non par position. L'ordre n'est important que pour l'assignation (prochain paramètre = prochaine valeur non utilisée).

    Un exemple (MySQL) :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    DM.DBLocal.ExecSQL('SELECT BodyID FROM Sales_Body WHERE ID=:ID AND ParentID=<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />arentID AND Code=GetDBCode("ReserveUsed") INTO @UsedID;'
                      +'UPDATE Sales_Body SET Active = 0 WHERE ID = :ID AND ParentID = <img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />arentID;'
                      +'UPDATE Reservation SET UsedID = NULL WHERE ID = :ID AND UsedID = @UsedID;',
                      [ID, qSaleBodyParentID.AsInteger]);

  3. #3
    Rédacteur/Modérateur

    Bonjour,

    Tu me confortes dans l'idée de la possiblité de mettre plusieurs SQL en un seul EXECSQL même si je suis frileux à ce sujet.
    Mais, d'un autre côté ton exemple est un cas particulier, chacun des SQL ayant les mêmes paramêtres.

    par contre
    TFDConnection traite les paramètres par nom et non par position.

    cette assertion me semble fausse, pour preuve tu peux remplacer les paramêtres nommés par des ?, je dirais donc plutôt qu'il s'agit des positions plutôt que des noms. Cela risque de devenir un débat

    Il faut vraiment que je me replonge dans ma bible, mais comme c'est quand même un cas particulier je ne sais si je vais découvrir le pot aux roses. Je vais peut-être posé la question sur le forum Embarcadero, Dmitry Arefiev semble encore y répondre de temps en temps on aurait la réponse de l'auteur principal.
    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

  4. #4
    Rédacteur/Modérateur

    Après épluchage de la "Bible", c’est-à-dire une recherche dans la table des matières et lecture des diverses pages pointées j'ai ceci qui tranche le débat et répond à ma question (page 120/121)

    je résume le paragraphe en extrayant et traduisant une phrase (répétée sous diverses formes)
    Citation Envoyé par Cary Jensen

    Lorsque vous utilisez des paramètres de position, vous devez fournir une valeur pour chaque marqueur de paramètre de position
    Donc, pour me répondre, non il n'y a pas moyen (dans le cas d'un FDConnection.ExecSQL) de réduire.
    Je crois que dans le cas particulier d'un FDConnection que les paramètres soient nommés ou non, cela reste des paramètres positionnels (à confirmer)

    @AndNotOr dans ton exemple quid en cas de gestion de la transaction ?
    1 - Déjà, comme j'avais pu le découvrir, la transaction qui est utilisée est-celle de la propriété Transaction et non UpdateTransaction.
    2- Si aucun FDTransaction n'est défini alors le comportement va peut-être bien différer entre les versions ante 10.4 et post 10.4 cf ce billet
    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
    Rédacteur/Modérateur

    Les paramètres anonymes sont sans doute traités par position (comment pourrait-il en être autrement) mais les paramètres nommés sont traités par nom au niveau de TFDConnection. TFDQuery lui laisse le choix par sa propriété BindMode mais est par nom par défaut.

    A noter que les paramètres anonymes, sans être dépréciés, ne sont pas recommandés non plus

    Ici :Qty est utilisé à deux reprises dans la même requête :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    DM.DBLocal.ExecSQL('INSERT INTO Invoices_Body (ID, BodyID, InvoiceID, StockID, RefID, Qty) '
                      +' VALUES '
                      +'(:ID, @BodyID, :InvoiceID, :StockID, :RefID, :Qty) '
                      +'ON DUPLICATE KEY UPDATE Qty=Qty +:Qty;',
                      [Invoice.ID, Invoice.InvoiceID, aID, aRefID, aQty])

###raw>template_hook.ano_emploi###