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 :

Requête ne renvoyant aucun résultat


Sujet :

Bases de données Delphi

  1. #1
    Candidat au Club
    Inscrit en
    Novembre 2012
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Novembre 2012
    Messages : 9
    Points : 3
    Points
    3
    Par défaut Requête ne renvoyant aucun résultat
    Bonjour,

    Désolé par avance si ce sujet a plus sa place dans le forum Access mais il s'agit bien d'un souci que je rencontre sous Delphi.

    J'ai cette requête :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT ID_S_Object 
    FROM S_Object 
    WHERE ID_S_Object_Type = :pID_OT 
    AND bFolder = :pFolder 
    AND NOT EXISTS (
      SELECT 1
      FROM D_Data_Table
      WHERE ID_S_Object=S_Object.ID_S_Object 
      AND ID_S_Attribute= :pID_Attribute)
    qui me renvoie une 20aine de résultats lorsque je la teste directement dans l'éditeur de base de données ACCESS.

    Les 3 paramètres sont des entiers (0, 6 et 39 pour mon test).

    Son rôle consiste à trouver les lignes (ID_S_Object) d'une table (S_Object) qui n'ont pas d'équivalent dans une autre (D_Data_Table).

    Lorsque je l’exécute sous Delphi avec un composant TADOQuery, elle me renvoie 0 résultat. Elle ne plante pas, c'est juste que mon composant Query a sa propriété ".eof" à vrai dès le départ après le ".Open". Je précise que j'ai des centaines d'autres requêtes qui fonctionnent très bien.

    J'ai également le souci avec une requête similaire :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT ID_S_Object 
    FROM S_Object 
    WHERE ID_S_Object_Type = :pID_OT 
    AND bFolder = :pFolder 
    AND ID_S_Object NOT IN (
      SELECT DISTINCT ID_S_Object 
      FROM D_Data_Table 
      WHERE ID_S_Attribute = :pID_Attribute)
    que j'ai testé "au cas où"... Elle est sensée renvoyer la même chose ; ce qu'elle fait d'ailleurs quand je l’exécute directement dans ACCESS.

    Voilà... Quoi d'autre ? POur la chaine de connexion, j'utilise le provider "Microsoft.Jet.OLEDB.4.0". Mon curseur est en clUseClient. Je n'ai pas de paramètres de connexion exotique (juste user id, data source et catalog).

    Je lance une bouteille à la mer au cas où.

    Ha oui, dernière chose : la requête fonctionne avec SQLServer (via un composant TADOQuery).

    Merci d'avance

  2. #2
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 784
    Points : 5 915
    Points
    5 915
    Par défaut
    Bonjour,

    On pourrait voir le code Delphi qui gère ces requêtes ? La chaine de connexion utilisée ?
    Que donne le découpage de ces requêtes puis leur exécution sous Delphi ?
    Philippe.

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 455
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 455
    Points : 24 867
    Points
    24 867
    Par défaut
    Est-ce que le composant ADO gère correctement les paramètres dans les sous-requetes ?

    Sinon, le NOT IN doit pouvoir s'écrire avec LEFT JOIN et WHERE IS NULL

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT S_Object.ID_S_Object 
    FROM S_Object 
    LEFT JOIN D_Data_Table ON D_Data_Table.ID_S_Object = S_Object.ID_S_Object 
      AND D_Data_Table.ID_S_Attribute = :pID_Attribute
     
    WHERE ID_S_Object_Type = :pID_OT 
    AND bFolder = :pFolder 
    AND D_Data_Table.ID_S_Object IS NULL

    Cela renvoie les S_Object.ID_S_Object présent dans S_Object mais manquant dans D_Data_Table filtrer sur l'attribut
    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

  4. #4
    Candidat au Club
    Inscrit en
    Novembre 2012
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Novembre 2012
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Bonjour et merci pour vos réponses. Désolé, je n'ai pas pu répondre plus tôt.

    Le composant TADOConnection est créé avec les options par défaut. La chaîne de connexion est la suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;Data Source=****\**.mdb;Mode=Share Deny None;Jet OLEDB:System database="";Jet OLEDB:Registry Path="";Jet OLEDB:Database Password="";Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don''t Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False;
    Personnellement, je ne définis pas toutes ces options. Uniquement le provider et le Data Source dans le cas d'Access.

    Le composant TADOQuery qui l'utilise est initialisé selon le code suivant.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    result := TADOQuery.Create(nil);
      result.Connection := AConnection;
      result.DisableControls;
      result.CursorLocation := ACursorLocation;
      if not AConnection.Connected then
        AConnection.Open;
    avec ACursorLocation = clUseClient dans ce cas (et AConnection un objet de connexion permanent).

    Le code qui est exécuté est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Query.SQL.Text := C_Query; //<-ma requête
    Set_Parameter(Query, 'pFolder', false);
    Set_Parameter(Query, 'pID_OT', Get_Attribute_ID_OT(AID_Attribute));
    Set_Parameter(Query, 'pID_Attribute', AID_Attribute);
     
    Query.Open;
    while not Query.eof do
    begin
      result.Add(IntToStr(Query.Fields[0].asInteger));
      Query.Next;
    end;
    Query.Close;
    Les fonctions Set_Parameter permettent d'assigner des valeurs ainsi que leur type au divers paramètres. J'en ai 5 ou 6 du type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    with AQuery.Parameters.ParamByName(AParameter) do
    begin
      DataType := ftInteger;
      if (AValue>0) or not AConsider_As_ID then
        Value := AValue
      else
        Value := NULL;
    end;
    Elles ont toutes leur spécificité. Celle pour les entiers insère des NULL à la demande si l'on envoie 0, celle pour les booléens les traite comme des entiers et insère -1 ou 1 suivant le type de SGBD, celle pour les float gère les NaN, les infinites, etc, celle pour les chaînes utilise du widestring pour gérer l'internationalisation, etc. Les buts de ces fonctions sont d'une part de forcer le type du paramètre car j'ai déjà eu des soucis dans le passé en faisant une simple affectation de la valeur et pas celle du DataType et par ailleurs de diminuer la taille des codes écrits (une ligne à la place de 5 ou 6) quand vos requête d'insert ont 50 paramètres, c'est cool
    Je vais tester vos diverses hypothèses.

  5. #5
    Candidat au Club
    Inscrit en
    Novembre 2012
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Novembre 2012
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Bonjour, j'ai testé plusieurs configurations différentes de ma requête initiale en n'utilisant pas systématiquement les paramètres mais en affectant directement les valeurs. Le résultat semble indiquer qu'il s'agit effectivement un problème de gestion des paramètres.

    Si j'utilise des paramètres pour bFolder et ID_S_Object_Type mais pas ID_S_Attribute, la requête fonctionne.

    Si j'utilise des paramètres pour ID_S_Attribute et pas pour bFolder, ni ID_S_Object_Type, la requête fonctionne.

    Pour tout autre configuration, la requête ne fonctionne pas. Donc en résumé, ça marche quand les paramètres appartiennent à la même requête.

    @Shai : j'ai testé ta requête. J'ai dû "parenthéser" un peu pour qu'elle fonctionne sous Access et rajouter un "Left". Sous access, elle donne les mêmes résultats que les deux autres. Et sous Delphi également, à savoir aucun :p
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT S_Object.ID_S_Object 
    FROM (S_Object 
    LEFT OUTER JOIN D_Data_Table ON (D_Data_Table.ID_S_Object = S_Object.ID_S_Object AND D_Data_Table.ID_S_Attribute = :pID_Attribute)) 
    WHERE ID_S_Object_Type = :pID_OT 
    AND bFolder = :pFolder 
    AND D_Data_Table.ID_S_Object IS NULL
    Au final, je pense que je vais écrire en dur le paramètre de la sous-requête dans le cas d'access (à moins que vous ayez une meilleure idée).

  6. #6
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 784
    Points : 5 915
    Points
    5 915
    Par défaut
    Bonjour,
    Citation Envoyé par llae_ Voir le message
    Elles ont toutes leur spécificité. Celle pour les entiers insère des NULL à la demande si l'on envoie 0
    Tester si une valeur est égale à NULL est totalement nul !!!
    En gros, vous allez écrire une requête syntaxiquement FAUSSE :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    select * from MATABLE
    where MACOLONNE = NULL

    Relisez cet article de Frédéric Brouard : les NULL
    Philippe.

  7. #7
    Candidat au Club
    Inscrit en
    Novembre 2012
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Novembre 2012
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Les Set_Parameter me servent également pour les INSERT et UPDATE
    Un exemple :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    UPDATE S_Object
    SET
      ID_S_Object_Parent = :pID_Parent
    WHERE ID_S_Object = :pID_Object

    Quand j'écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Set_Parameter('pID_Parent',ID_Parent,true);
    ca m'écrit null si ID_Parent vaut 0 et une valeur entière positive dans le cas contraire.

    Dans le cas de condition à NULL, j'écris effectivement des codes du style
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT ID_S_Object
    FROM S_Object
    WHERE ID_S_Object_Parent IS NULL
    sans passer par des paramètres.

    Au pire, si un dév. utilise cette fonction pour des conditions NULL, ça lui pète une erreur SQL et il finit par comprendre l'embrouille.

  8. #8
    Candidat au Club
    Inscrit en
    Novembre 2012
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Novembre 2012
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    J'ai quand même rajouté un warning dans le header de la fonction pour prévenir certains développeurs un peu tête en l'air
    Merci pour la remarque.

Discussions similaires

  1. Requête juste mais aucun résultat !
    Par Darknitro dans le forum Requêtes
    Réponses: 13
    Dernier message: 05/10/2012, 08h07
  2. Requête ne retournant aucun résultat
    Par Arbooch dans le forum Forms
    Réponses: 5
    Dernier message: 07/08/2009, 10h59
  3. [MySQL] Savoir si la requête ne retourne aucun résultat
    Par mickado dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 06/04/2007, 09h37
  4. Réponses: 1
    Dernier message: 29/09/2005, 12h05
  5. PSQLException "Aucun résultat retourné par la requête&q
    Par BRAUKRIS dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 15/09/2005, 20h55

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