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

SQL Firebird Discussion :

Paramètre avec valeurs multiples


Sujet :

SQL Firebird

  1. #1
    Membre à l'essai
    Paramètre avec valeurs multiples
    Bonjour,

    Je n'arrive pas à réaliser la requête suivante :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    select * from matable where matable.monchamp in (:parametre)


    Le paramètre doit prendre des string en valeur. Si je passe une seule valeur, pas de soucis. Si je passe deux valeurs (ex. : 'A','B'), soit je n'ai aucun retour (alors qu'il en faudrait un), soit cela génère une erreur.

    J'ai cherché sur le net mais je n'ai rien trouvé de particulier par rapport à cela ou une solution. J'ai testé la même chose en MySql et cela fonctionne

    Merci d'avance pour votre aide

  2. #2
    Rédacteur/Modérateur

    Bonjour,

    Manque d'informations.

    Si la requête est passée via un composant Delphi , si oui, lequel ?
    S'il s'agit de Firedac utilisez la macro
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    select * from matable where matable.monchamp in (&parametre)

    MacroByName('parametre').asRaw:= QuotedStr('A')+','+QuotedStr('B');

    Cependant, si je regarde l'historique de vos messages je crains qu'il ne s'agisse de IBQuery qui lui n'a pas la possibilité des Macros
    Un code à essayer :
    Code pascal :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    var SL : TStringList;
    begin
     SL:=TStringList.Create;
     SL.Add(QuotedStr('A'));
     SL.Add(QuotedStr('B'));
     IBQuery.ParamByName('parametre').asString:=Quotedstr(SL.CommaText);
     SL.Free;



    S'il s'agit d'autre chose, il faut expliciter comment vous exécuter et vous passez le paramètre
    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) 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
    Membre à l'essai
    Merci pour ce premier retour. Dans un premier temps, j'essaye simplement de le faire fonctionner dans les managers de db tel qu'EMS et Ibexpert. Sur les deux logiciels, comportement similaire à ce que j'ai dit dans mon premier post

    Je l'ai également fait en Delphi en utilisant le composant ibobject et en appelant comme ceci :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    param_query.ParamByName('niveau').AsString := 'SI,SS';


    Même résultat, aucun record renvoyé alors qu'il y a bien des données.

    La version de Firebird est la 2.5
    La version de Delphi est XE2

    Merci d'avance pour l'aide

  4. #4
    Rédacteur/Modérateur

    Ce n'est pas un problème Firebird mais plus de la manière de présenter le paramètre

    Avec les guillemets "A","B" serait à essayer
    avec les doubles quotes cela devient vite invivable ''A'',''B'' dès que l'on va tenter de le coder avec Delphi
    Code pascal :Sélectionner tout -Visualiser dans une fenêtre à part
    param:='''A'',''B'''

    La suggestion StringList est à prendre en compte
    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) 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
    Membre à l'essai
    Avant même delphi, j'essaye de le faire fonctionner en Sql, ce qui ne va pas.

    J'ai essayé les simples quotes, les doubles quotes dans la fenêtre proposant d'encoder les valeurs et cela ne change absolument rien.

    Voici ce que j'ai déjà tapé dans le prompt :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    'SI','SS'
    "SI","SS"
    SI,SS


    J'avais également testé ton écriture sous delphi mais cela ne donne rien non plus. Pour l'idée du TstringList, je ne vois pas comment je pourrais le passer à mon paramètre en Delphi.

  6. #6
    Rédacteur/Modérateur

    Avec DBeaver 7.0 cela fonctionne


    pour delphi une solution ?

    Code Delphi :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    var SL : TStringList;
    begin
     SL:=TStringList.Create;
     SL.Add(QuotedStr('AC'));
     SL.Add(QuotedStr('CC'));
     IBQuery.Close;
     IBQuery.SQL.Text:='SELECT * FROM APPOSE WHERE CODE APPOSE IN('+SL.CommaText+')'; 
     IBQuery.Open;
     SL.Free;
    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) 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

  7. #7
    Membre à l'essai
    Hello,

    J'ai également testé DBeaver. J'ai l'impression qu'il remplace à la volée le SQL plutôt que d'avoir un prompt. Raison pour laquelle cela fonctionnerait.

    J'ai essayé avec isql mais sauf erreur de ma part, cet outil ne prend pas les paramètres dans les query.

    Du côté de Delphi, ma requête n'est hélas pas aussi simple et comporte environ 15 lignes dans la where clause (commentaires compris). Je pourrais bien entendu l'ajouter dans le code mais cela ajouterai un grand nombre de ligne et je perdrai en lisibilité.
    Pour le composant ibo, je n'ai pas vu d'autres manières de passer les paramètres

    Savez-vous s'il est possible en Delphi de récupérer le sql complet envoyé à la db ? En effet,
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    maquery.sql.text
    ne comporte pas les valeurs affectés au paramètre.

    Merci pour l'idée du tstinglist que je garde pour le futur

  8. #8
    Rédacteur/Modérateur

    Citation Envoyé par lave_01 Voir le message

    J'ai également testé DBeaver. J'ai l'impression qu'il remplace à la volée le SQL plutôt que d'avoir un prompt. Raison pour laquelle cela fonctionnerait.
    Du côté de Delphi, ma requête n'est hélas pas aussi simple et comporte environ 15 lignes dans la where clause (commentaires compris).
    Hé bien je vous propose de "simuler" une macro
    Exemple avec IBQuery :
    Code delphi :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    procedure TForm107.btn1Click(Sender: TObject);
    var SL : TStringList;
    const SQL : 'SELECT * FROM APPOSE WHERE CODE_APPOSE IN (&Liste)' ;
    begin
    SL := TStringList.Create;
    SL.Add(QuotedStr('CC'));
    SL.Add(Quotedstr('AC'));
    IBQuery1.Active:=false;
    IBQuery1.SQL.Text:=StringReplace(SQL,'&Liste',SL.CommaText,[rfReplaceAll]);
    SL.Free;
    IBQuery1.Active:=True;
    end;

    Ceci fonctionne et en même temps, si vous vérifiez SQL.Text vous aurez bien SELECT * FROM APPOSE WHERE CODE_APPOSE IN (''CC'',''AC'');
    inconvénient, le SQL de départ doit être dans une constante pour pouvoir le réutiliser autre inconvénient il faut absolument qu'il y ait un élément dans la StringList
    contournement mettre la clause entière comme macro
    Code delphi :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    const SQL : 'SELECT * FROM APPOSE WHERE CODE_APPOSE IN (&Liste)' ;
    ...
    IBQuery1.SQL.Text:=StringReplace(SQL,'&Liste',' CODE_APPOSE IN ('+SL.CommaText+')',[]);
    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) 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

  9. #9
    Membre émérite
    AMHA pourquoi pas crée une table qui contient ces constant alphanumériques
    je préfère utiliser les constants numériques
    en plus tu gard la notion du SGBDR,
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

  10. #10
    Membre à l'essai
    Hello,

    Merci pour ton retour mais pourrais-tu développer un peu plus car je ne vois pas comment tu y arriverais.

    Pour le moment, j'ai implémenté en partie la solution de SergioMaster. Je dois encore finaliser quelques tests et je reviens vers vous pour vous donner la solution mise en place au final. cela pourra toujours servir à d'autres au besoin

    Merci et bonne journée,

    Valéry

  11. #11
    Rédacteur/Modérateur

    Bonjour
    Citation Envoyé par lave_01 Voir le message
    un peu plus car je ne vois pas comment tu y arriverais.
    Compliqué mais possible en utilisant une GTT (global temporary table) et une union.
    Compliqué dans le sens où :
    a) il faut que la structure de la GTT soit crée
    ie.
    Code SQL :Sélectionner tout -Visualiser dans une fenêtre à part
    CREATE TABLE PARAMGTT(CODE CHAR(2)) ON COMMIT PRESERVE ROWS;

    b) le programme doit remplir la table , la vider ne posant pas de souci, encore qu'il faille faire attention au 'ON COMMIT'
    - DELETE ROWS alors il faudra gérer la transaction
    - PRESERVE ROWS par précaution vider la table avant de la remplir
    c) le SQL change si je reprends mon exemple cela deviendrait
    Code SQL :Sélectionner tout -Visualiser dans une fenêtre à part
    SELECT a.* FROM APPOSE a JOIN PARAMGTT p ON a.CODE_APPOSE=p.CODE
    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) 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

  12. #12
    Membre à l'essai
    On est d'accord, c'est un peu extrême

    Merci pour d'avoir détaillé

  13. #13
    Membre émérite
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

  14. #14
    Rédacteur/Modérateur

    Bonjour

    @edam, comment dire tu es à côté de la plaque, hors sujet.

    Tout d'abord tu utilises mon exemple et "mes données" ce qui n'est pas vraiment le sujet de départ, celui-ci je l'ai mis juste pour illustrer.

    Je rappelle que le sujet est
    Je n'arrive pas à réaliser la requête suivante :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    select * from matable where matable.monchamp in (:parametre)
    Sujet hors cadre de Firebird puisqu'il s'agit de fait d'une interrogation Delphi ou même de GUIs externes.
    Citation Envoyé par lave_01
    j'essaye simplement de le faire fonctionner dans les managers de db tel qu'EMS et Ibexpert.
    J'ai pu démontrer, avec mon exemple, que certains GUI (DBWeaver) pouvait le faire, d'où l'utilisation de la table APPOSE d'une de mes applications et ce afin de prouver que ce n'était pas un problème Firebird.
    Suite à mes suppositions de départ et ma connaissance de Firedac, j'ai également proposé, après quelques tâtonnements je l'avoue, une solution Delphi viable avec des connecteurs de composants autre que Firedac ne connaissant pas les macros en l'occurence IBX (comme j'ai tendance à confondre avec un autre set de composants je préfère IBX à l'IBObjects cité )

    Ton intervention peu claire, méritait une explication sur les possibilités au niveau Firebird, le fait d'utiliser des id numériques au lieu de valeurs chaînes, je l'écarte car hors de propos, de toute façon la solution serait identique.

    Citation Envoyé par Edam
    1- comment l'utilisateur choisi ces codes : combobox rempli avec des données statiques ?
    Nulle part nous n'avons parlé de combobox ou de mode de saisie, vous qui vouliez être "SGBDR", nous amenez de l'interface utilisateur
    Citation Envoyé par Edam
    2-la colonne "CODE_APPOSE" est liée, indexée?

    Quelle importance, c'est un exemple, pour information Oui elle est indexée et est même une référence, s'il n'y a pas ID_Technique c'est que :
    - la table est de faible volume (une 20 de lignes)
    - doit être figée (pas de possibilité de changer le code une fois celui-ci utilisé)
    - j'ai été flemmard à l'époque (siècle dernier) lors de la création de la structure de la table
    mais, encore une fois cela n'a rien à voir, la demande aurait pu porter sur une colonne libellé.
    Citation Envoyé par Edam
    Je préfère utilise TClientDataset.
    Encore une fois, un mélange entre Delphi (TClientDataset) et Firebird alors que vous indiquez que vous voulez garder la notion du SGBDR.
    Citation Envoyé par Edam
    sergio; je ne parle pas d'une table temporaire, et je n'ai jamais utiliser,

    C'est bien dommage car c'est bien pratique en tout cas cela n'utilise pas de Clientdataset
    Si j'ai proposé cette utilisation de GTT c'est uniquement pour éclaircir une vraie possibilité même si
    Citation Envoyé par Lave_01
    On est d'accord, c'est un peu extrême

    je ne commente pas le reste (le code et la proposition d'une table supplémentaire inutile)
    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) 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