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

WinDev Discussion :

Requête SQL dynamique paramétrée [WD23]


Sujet :

WinDev

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 123
    Points : 84
    Points
    84
    Par défaut Requête SQL dynamique paramétrée
    Bonjour,

    Est-il possible de construire une requête SQL dynamique, et de lui fournir des paramètres ?

    Exemple, je peux faire ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    sql est une chaîne = "update foo set bar = {p_bar}"
    source est une Source de Données
    source.p_bar = "FOOBAR"
    HExécuteRequêteSQL(source, hRequêteDéfaut, sql)
    Comment faire si je ne connais pas le nom de mon paramètre ?

    Mon premier réflexe était d'utiliser l'indirection :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    sql est une chaîne = "update foo set bar = {p_bar}"
    nomparam est une chaîne = "p_bar"
    source est une Source de Données
    source.{nomparam} = "FOOBAR"
    HExécuteRequêteSQL(source, hRequêteDéfaut, sql)
    Mais ce n'est pas supporté.
    Le but, in fine, est de construire une méthode qui prenne en entrée une requête SQL source forme de chaine et un tableau associatif, et qui soit capable de "binder" correctement les paramètres et d'exécuter HExécuteRequêteSQL.

    Mais je ne sais pas comment faire avec Windev.

    (et je précise que je ne veux évidemment pas inclure les valeurs des paramètres directement lors de la construction du code SQL de la requête)

    Merci pour votre aide.

  2. #2
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2003
    Messages
    999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Alimentation

    Informations forums :
    Inscription : Mai 2003
    Messages : 999
    Points : 2 099
    Points
    2 099
    Par défaut
    Bonjour,

    Oui de cette manière:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    taMesParametres est un tableau associatif de chaînes
    sql est une chaîne = "update foo set bar = {p_bar}"
    source est une Source de Données
     
    POUR TOUT sParametre,sCle de taMesParametres
    	sql = Remplace(sql,"{[%sCle%]}",sParametre)
    FIN
     
    HExécuteRequêteSQL(source, hRequêteDéfaut, sql)
    Par contre il faut bien évidemment penser à mettre des quotes là où ce sera nécessaire et à traiter les caractères particuliers. Pour le coup il serait plus judicieux d'utiliser un tableau associatif de variant et de tester le type pour le traiter correctement (date, entier, chaine,...)

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 123
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par philouZ Voir le message
    Bonjour,

    Oui de cette manière:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    taMesParametres est un tableau associatif de chaînes
    sql est une chaîne = "update foo set bar = {p_bar}"
    source est une Source de Données
     
    POUR TOUT sParametre,sCle de taMesParametres
    	sql = Remplace(sql,"{[%sCle%]}",sParametre)
    FIN
     
    HExécuteRequêteSQL(source, hRequêteDéfaut, sql)
    )
    Bonjour,

    Merci, mais c'est précisément ce que je veux éviter.
    Là, sauf erreur, ce ne sont pas de "vrais" paramètres, mais une simple modification de la requête SQL pour insérer dynamiquement les bonnes valeurs aux bons endroits.
    Ce n'est pas ce que je veux faire, je voudrais pouvoir utiliser de vrais paramètres.

    cf https://doc.pcsoft.fr/fr-FR/?3044084...RAGRAPHE000523


    Citation Envoyé par philouZ Voir le message
    Bonjour,
    Par contre il faut bien évidemment penser à mettre des quotes là où ce sera nécessaire et à traiter les caractères particuliers. Pour le coup il serait plus judicieux d'utiliser un tableau associatif de variant et de tester le type pour le traiter correctement (date, entier, chaine,...)
    Justement, l'un des intérêts d'utiliser de vrais paramètres est de ne pas se soucier d'avoir à nettoyer les chaines en amont.

  4. #4
    Expert confirmé
    Avatar de Voroltinquo
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Juin 2017
    Messages
    2 881
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chef de projet en SSII

    Informations forums :
    Inscription : Juin 2017
    Messages : 2 881
    Points : 5 449
    Points
    5 449
    Billets dans le blog
    1
    Par défaut
    Bonjour,
    Il faut passer par une variable requête SQL et non par une chaîne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    REQ_MaRequête est Requête SQL=
    [
    update foo set bar = {p_bar}
    ]
    REQ_MaRequête.p_bar="FOOBAR"
    HExécuteRequête(REQ_MaRequête)
    Tout est détaillé là : https://doc.pcsoft.fr/?1514082

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 123
    Points : 84
    Points
    84
    Par défaut
    Bonjour,

    Citation Envoyé par Voroltinquo Voir le message
    Bonjour,
    Il faut passer par une variable requête SQL et non par une chaîne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    REQ_MaRequête est Requête SQL=
    [
    update foo set bar = {p_bar}
    ]
    REQ_MaRequête.p_bar="FOOBAR"
    HExécuteRequête(REQ_MaRequête)
    Tout est détaillé là : https://doc.pcsoft.fr/?1514082
    Oui, je connais tout ça mais cela ne répond pas à ma question.
    Dans ton exemple, comme rendre le "p_bar" dynamique ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    REQ_MaRequête.p_bar="FOOBAR"

  6. #6
    Expert confirmé
    Avatar de Voroltinquo
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Juin 2017
    Messages
    2 881
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chef de projet en SSII

    Informations forums :
    Inscription : Juin 2017
    Messages : 2 881
    Points : 5 449
    Points
    5 449
    Billets dans le blog
    1
    Par défaut
    [QUOTE=fred_malette;11584699
    Dans ton exemple, comme rendre le "p_bar" dynamique ?
    [/QUOTE]
    En utilisant une variable chaine par exemple, comme on le ferait avec une requête enregistrée dans l'analyse.
    Dans ce que tu veux faire, tu peux créer une chaîne qui comporte toutes les valeurs séparées par TAB et dans l'exécution, découper la chaine passée en paramètre.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 123
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par Voroltinquo Voir le message
    En utilisant une variable chaine par exemple, comme on le ferait avec une requête enregistrée dans l'analyse.
    Justement, je n'arrive pas à le faire et il semble que ce ne soit pas supporté par Windev, mais si tu peux me donner un exemple, je suis preneur et t'en remercie !

    Citation Envoyé par Voroltinquo Voir le message
    Dans ce que tu veux faire, tu peux créer une chaîne qui comporte toutes les valeurs séparées par TAB et dans l'exécution, découper la chaine passée en paramètre.
    Pas sûr de bien saisir. Dans un monde idéal (ou dans un environnement autre que Windev ) j'aurais en entrée une chaîne SQL correspondant à ma requête et un tableau associatif correspondant à mes paramètres, et je pourrais "injecter" mes paramètres proprement avant l'exécution de ma requête. Exactement comme le proposait philouZ un peu plus haut, sauf que je souhaite passer par de vrais paramètres et pas par du simple bidouillage de chaîne.

  8. #8
    Expert confirmé
    Avatar de Voroltinquo
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Juin 2017
    Messages
    2 881
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chef de projet en SSII

    Informations forums :
    Inscription : Juin 2017
    Messages : 2 881
    Points : 5 449
    Points
    5 449
    Billets dans le blog
    1
    Par défaut
    Un exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    REQ_MaRequête.Param=sValeurParamètre
    Prenons le cas de la requête suivante :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT
    Client.PK_Client
    FROM
    Client
    WHERE
    Client.NDX_SexeClient={pSexe}

    On peut par exemple utiliser une fonction pour sélectionner les hommes ou les femmes (mailing pour fête des pères ou des mères)
    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
    FONCTION ClientSelonSexe(sSexe est chaine) : entier
    REQ_SelectSexe est Requête SQL =
    [
    SELECT
    Client.PK_Client
    FROM
    Client
    WHERE
    Client.NDX_SexeClient={pSexe}
    ]
     
    REQ_SelectSexe.pSexe=sSexe
    HExecuteRequete(REQ_SelectSexe)
    Renvoyer Faux
     
    CAS ERREUR
         Renvoyer HErreurInfo(hErreurCodeSystème)

  9. #9
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2003
    Messages
    999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Alimentation

    Informations forums :
    Inscription : Mai 2003
    Messages : 999
    Points : 2 099
    Points
    2 099
    Par défaut
    Ce que tu souhaites faire en dehors de la méthode que je t'ai citée plus haut n'est pas possible. Extrait de l'aide:
    •La requête doit être définie dès sa déclaration. Il n'est pas possible de déclarer une variable de type Requête SQL puis de saisir le code SQL correspondant après quelques lignes de code.
    •La requête SQL ne peut pas être construite avec des concaténations de chaînes.
    Ce que te donne Voroltinquo n'est pas valable pour une requête saisie dynamiquement.

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 123
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par Voroltinquo
    ...
    Merci, mais cela ne répond pas à ma question. Ici, ton paramètre (pSexe) n'est pas dynamique.


    Citation Envoyé par philouZ
    Ce que tu souhaites faire en dehors de la méthode que je t'ai citée plus haut n'est pas possible.
    Effectivement, d'après ce que j'ai vu de l'aide, je crains que cela ne soit pas possible. Mais j'espérais l'existence d'une astuce.

    (c'est quand même dingue qu'en 2020 Windev ne supporte pas l'ajout de paramètres dynamiques sur une requête SQL, enfin bref, peut-être en version 26...)

    Tant pis et merci pour votre temps.

  11. #11
    Expert confirmé
    Avatar de Voroltinquo
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Juin 2017
    Messages
    2 881
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chef de projet en SSII

    Informations forums :
    Inscription : Juin 2017
    Messages : 2 881
    Points : 5 449
    Points
    5 449
    Billets dans le blog
    1
    Par défaut
    Ne parlerais tu pas plutôt, non pas du paramètre, mais de la colonne de la table sur laquelle doit se faire la requête (eg sélection sur le pays ou sur la date de naissance ?)

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 123
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par Voroltinquo Voir le message
    Ne parlerais tu pas plutôt, non pas du paramètre, mais de la colonne de la table sur laquelle doit se faire la requête (eg sélection sur le pays ou sur la date de naissance ?)
    Non non je parle bien du paramètre.

    (les noms des colonnes aussi sont dynamiques mais de ce côté ça fonctionne très bien, le problème n'est pas là, ce sont les paramètres que je veux rendre dynamiques)

  13. #13
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 280
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 280
    Points : 12 974
    Points
    12 974
    Par défaut
    Bonjour,
    Je ne vois pas en quoi la proposition de Voroltinquo ne répond pas à la demande.
    {pSexe} peut être remplacé par "n'importe quelle valeur", et sSexe est une variable.

    Tu peux modifier le contenu d'une variable comme bon te semble, donc il s'agit bien d'une requête paramétrable.
    Rien ne t'empêche d'utiliser le contenu d'un champ de saisie à la place d'une variable.
    Tu peux aussi lancer plusieurs fois la même requête, en utilisant à chaque fois une variable différente.
    Tu peux même utiliser une indirection, ainsi même la variable utilisée est dynamique, i.e. choisie à l'exécution.

    Tatayo.

  14. #14
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 123
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par tatayo Voir le message
    Bonjour,
    Je ne vois pas en quoi la proposition de Voroltinquo ne répond pas à la demande.
    {pSexe} peut être remplacé par "n'importe quelle valeur", et sSexe est une variable.
    Justement, c'est bien là le problème, {pSexe} ne peut pas être remplacé par n'importe quelle variable (en tout cas, ça ne fonctionne pas chez moi, et la doc de Windev précise qu'on ne peut pas faire d'indirection sur les noms des paramètres).

    Pour résumé, ce que propose Voltinquo c'est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    REQ_SelectSexe.pSexe=sSexe
    Moi, je cherche un moyen de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    sNomParametre = "pSexe"
    REQ_SelectSexe.{sNomParametre}=sSexe

  15. #15
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2003
    Messages
    999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Alimentation

    Informations forums :
    Inscription : Mai 2003
    Messages : 999
    Points : 2 099
    Points
    2 099
    Par défaut
    ...la doc de Windev précise qu'on ne peut pas faire d'indirection sur les noms des paramètres
    Ce n'est pas vrai, tu peux faire des indirections sur le paramètres en faisant comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    {"REQ_SelectSexe."+sNomParametre,indParamètreRequête}=sSexe
    J'ai dit que tu ne pouvais pas affecter ou modifier le code SQL d'une requête

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MaReq est une Requête SQL
    MaReq..CodeSQL = "select * from table"
    Ça c'est interdit !!!

  16. #16
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 280
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 280
    Points : 12 974
    Points
    12 974
    Par défaut
    Et pourtant je viens de regarder l'aide en ligne ici.
    On peut passer une valeur à un paramètre*; *si l'exemple utilise une chaine "en dur", rien n'interdit d'utiliser une variable.
    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    REQ_Clients_nom_prenom est une chaine = "SELECT * FROM CLIENT WHERE NOM = {Param1} AND PRENOM = {Param2}"
    sNom est un Variant = Null
    // Utilisation du variant obligatoire
    // pour variable de type Null (non renseignée)
     
    HExécuteRequête(REQ_Clients_nom_prénom, hRequêteDéfaut, ...
    sNom, "Jean")
     
    // OU
     
    HExécuteRequête(REQ_Clients_nom_prénom, hRequêteDéfaut, ...
    Null, "Jean")
    Tu peux voir qu'une variable est utilisée pour l'un des paramètres.
    Idem ici, rien n'indique qu'on ne peut pas utiliser une variable pour passer un paramètre, voir une indirection si tu ne peux pas spécifier "en dur" le nom de la variable utilisée.

    En relisant ta réponse je pense avoir compris. Effectivement tu ne peux pas mettre une variable dans la requête. Mais tu peux tout à fait passer par un paramètres à hExeccuteRequete(), comme je l'explique ci dessus.


    Tatayo.

  17. #17
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 129
    Points : 9 562
    Points
    9 562
    Par défaut
    L'exemple proposé par Tatayo est très explicite. Param1 et Param2 sont des paramètres, il n'y a pas de piège !
    Et la page d'aide qu'il a mis en lien donne aussi une autre information.

    On peut faire <Nom Requête>.<Param1> = xxx

    Dans le code, ça va donner sReq.param1 = 1 par exemple. Il n'y a absolument pas besoin des indirections { } mais il faut que sReq soit déclarée en tant que requete, pas en tant que chaine.

  18. #18
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 123
    Points : 84
    Points
    84
    Par défaut
    Bonjour,

    Citation Envoyé par philouZ Voir le message
    Ce n'est pas vrai, tu peux faire des indirections sur le paramètres en faisant comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    {"REQ_SelectSexe."+sNomParametre,indParamètreRequête}=sSexe
    Merci beaucoup, c'est exactement ça que je cherchais. J'ai cru, à tort, que c'était impossible. Parfait

    Citation Envoyé par tatayo
    En relisant ta réponse je pense avoir compris. Effectivement tu ne peux pas mettre une variable dans la requête. Mais tu peux tout à fait passer par un paramètres à hExeccuteRequete(), comme je l'explique ci dessus.
    Certes ... mais ce n'est pas vrai pour HExécuteRequêteSQL, or c'est cette fonction que j'utilise.

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

Discussions similaires

  1. Requête SQL dynamique avec nom de table dans une variable
    Par jonjack dans le forum SQL Procédural
    Réponses: 9
    Dernier message: 15/09/2011, 14h37
  2. Transformer une requête sql dynamique
    Par ttttnht dans le forum Sybase
    Réponses: 5
    Dernier message: 24/07/2007, 07h54
  3. Requête SQL avec paramètre sur BDD Access
    Par BigMike dans le forum Windows Forms
    Réponses: 3
    Dernier message: 07/06/2007, 12h21
  4. Réponses: 3
    Dernier message: 04/06/2007, 12h29
  5. requête SQL avec paramètre en vb avec base de donnée SQL srv
    Par dialydany dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 01/02/2005, 10h33

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