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

PureBasic Discussion :

Problème de requêtes SQL imbriquées


Sujet :

PureBasic

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 28
    Points : 18
    Points
    18
    Par défaut Problème de requêtes SQL imbriquées
    Bonjour à tous,

    Je bloque sur un aspect concernant le parcours du résultat des requêtes SQL en Purebasic. Voilà mon problème :

    Je souhaite alimenter une treeview avec toutes les catégories existantes dans ma base de données, sachant que certaines catégories sont parentes d'autres. Voici le schéma simplifié de ma table "CATEGORIES" :

    id_categorie INT PRIMARY KEY
    nom_categorie VARCHAR(100)
    parent_cat_id INT (clé étrangère)

    Et les données dans la table :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    id_categorie    |    nom_categorie                    | parent_cat_id
              1         |    Bureautique                        |           0
              2         |    Word                                 |           1
    Dans mon code, une première requete sélectionne toutes les catégories sans catégorie enfant, puis pour chacune, une seconde requête recherche si elle posède des catégories enfant et doit les afficher. Or, ça ne fonctionne pas car purebasic semble s'emmeler les pinceaux et considère apparemment qu'il n ya qu'un seul résultat de requete (enfin à ce qu'il me semble).

    Voici mon code :
    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
     
    If DatabaseQuery(1, "SELECT * FROM categories WHERE parent_categorie_id=0;" ) 
        While NextDatabaseRow(1) > 0 
            ; on récupère l'id de la catégorie
            id_cat.l = GetDatabaseLong(1,0)
            AddGadgetItem(#Lst_Categories, id_cat, GetDatabaseString(1,1) + " - " + GetDatabaseString(1,2),0, 0)
            ; on regarde s'il y a des catégories enfant
            If DatabaseQuery(1, "SELECT * FROM categories WHERE parent_categorie_id=id_cat;" ) 
                While NextDatabaseRow(1) > 0 
                    AddGadgetItem(#Lst_Categories, id_cat, GetDatabaseString(1,1) + " - " + GetDatabaseString(1,2),0, 1)
                Wend
     
            EndIf
                Wend 
        FinishDatabaseQuery(1) 
        CloseDatabase(1) 
    Else
        MessageRequester("ERREUR","Selection impossible"+Chr(13)+DatabaseError(),#PB_MessageRequester_Ok)
    EndIf
    Qu'est ce que je fais mal ?

    Merci de votre aide et à bientôt.

    Amicalement,

    Jean-Marc

  2. #2
    Responsable Purebasic

    Avatar de comtois
    Inscrit en
    Avril 2003
    Messages
    1 261
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 1 261
    Points : 9 924
    Points
    9 924
    Billets dans le blog
    8
    Par défaut
    En effet, tu ne peux pas imbriquer tes requêtes ainsi.
    J'ai déjà vu des réponses à ce problème, certains proposent d'utiliser une liste chainée intermédiaire pour stocker les résultats de la première requête.

    D'autres proposent de changer le numéro de la base pour chaque requête imbriquée.

    Par exemple :

    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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    Procedure.l ParseDatabase(name.s,user.s,password.s)
     
      ; Parse Databases
     
      dbDB = OpenDatabase(#PB_Any,name,user,password)
     
      If dbDB
     
        If DatabaseQuery(dbDB,"SHOW DATABASES")
     
          *conn.DATABASE = NewList2(DATABASE)
     
          While NextDatabaseRow(dbDB)
     
            *db.DATABASE = AddElement2(*conn)
            *db\name = GetDatabaseString(dbDB,0)
            *db\tables = NewList2(TABLE)
     
            ; Parse Tables
     
            dbTable = OpenDatabase(#PB_Any,name,user,password)
     
            If dbTable
     
              If DatabaseQuery(dbTable,"SHOW TABLES FROM " + *db\name)
     
                While NextDatabaseRow(dbTable)
     
                  *table.TABLE = AddElement2(*db\tables)
                  *table\name = GetDatabaseString(dbTable,0)
                  *table\fields = NewList2(FIELD)
     
                  ; Parse Fields
     
                  dbField = OpenDatabase(#PB_Any,name,user,password)
     
                  If dbField
     
                    If DatabaseQuery(dbField,"DESCRIBE " + *db\name + "." + *table\name)
     
                      While NextDatabaseRow(dbField)
     
                        *field.FIELD = AddElement2(*table\fields)
                        *field\name  = GetDatabaseString(dbField,0)
                        *field\type  = GetDatabaseString(dbField,1)
                        *field\null  = GetDatabaseString(dbField,2)
                        *field\key   = GetDatabaseString(dbField,3)
                        *field\def   = GetDatabaseString(dbField,4)
                        *field\extra = GetDatabaseString(dbField,5)
     
                      Wend
     
                    EndIf
     
                    CloseDatabase(dbField)
     
                  EndIf
     
                Wend
     
              EndIf
     
              CloseDatabase(dbTable)
     
            EndIf
     
          Wend
     
        EndIf
     
        CloseDatabase(dbDB)
     
      EndIf
     
      ProcedureReturn *conn
     
    EndProcedure
    Ce qui dans ton cas donnerait :

    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
     
    If DatabaseQuery(1, "SELECT * FROM categories WHERE parent_categorie_id=0;" ) 
      While NextDatabaseRow(1) > 0 
        ; on récupère l'id de la catégorie
        id_cat.l = GetDatabaseLong(1,0)
        AddGadgetItem(#Lst_Categories, id_cat, GetDatabaseString(1,1) + " - " + GetDatabaseString(1,2),0, 0)
        ; on regarde s'il y a des catégories enfant
        Enfant = OpenDatabase(#PB_Any, xxxxxxxxxxxxxx)
     
        If DatabaseQuery(enfant, "SELECT * FROM categories WHERE parent_categorie_id=id_cat;" ) 
          While NextDatabaseRow(Enfant) > 0 
            AddGadgetItem(#Lst_Categories, id_cat, GetDatabaseString(Enfant,1) + " - " + GetDatabaseString(Enfant,2),0, 1)
          Wend
            FinishDatabaseQuery(Enfant) 
            CloseDatabase(Enfant) 
        EndIf
      Wend 
      FinishDatabaseQuery(1) 
      CloseDatabase(1) 
    Else
      MessageRequester("ERREUR","Selection impossible"+Chr(13)+DatabaseError(),#PB_MessageRequester_Ok)
    EndIf
    Vous souhaitez participer à la rubrique PureBasic (tutoriels, FAQ, sources) ? Contactez-moi par MP.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 28
    Points : 18
    Points
    18
    Par défaut Solutions
    Bonjour Comtois et merci de ta contribution.

    Tes 2 solutions répondent effectivement à mon problème. je vais étudier les listes chainées, solution qui me semble la plus "propre". Cependant les 2 sont intéressantes et étendent fortement mes compétences en Purebasic.

    Même si je n'ai pas encore testé tout ça, je mets le post en "résolu"

    Encore merci de ta réactivité, bonne soirée et bon code à toi

    Amicalement,

    Jean-Marc

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 28
    Points : 18
    Points
    18
    Par défaut
    Re bonjour à tous,

    Finalement j'ai retiré la mention "RESOLU" car je galère encore un peu avec mon histoire de catégories et sous catégories.

    En fait, je ne sais pas à l'avance le niveau d'imbrication des catégories (ce sont les utilisateurs qui décident), j'ai essayé de faire ça :

    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
     
    id_item_liste = 0
    parent_id.l = 0
    Procedure ParcoursCategories(parent_id)
     
        If DatabaseQuery(1, "SELECT * FROM categories WHERE parent_categorie_id=" + Str(parent_id) + ";" ) 
            While NextDatabaseRow(1) > 0 
     
                AddGadgetItem(#Lst_Categories, id_item_liste, GetDatabaseString(1,1) + " - " + GetDatabaseString(1,2),0, 0)
     
                id_item_liste = id_item_liste + 1
                ; on récupère l'id de la catégorie
                id_cat.l = GetDatabaseQuad(1,0)
                parent_id = id_cat
                ParcoursCategories(parent_id)
            Wend
        EndIf      
    EndProcedure
    J'ai créé une procédure récursive, et tout naïf que je suis, je pensais que ça le ferais. Mais ce n'est pas du tout le cas, toujours le même problème je pense d'imbrication des requêtes SQL.

    Je vais essayer de modifier le code pour inclure si c'est possible les instructions de connexion à la BDD à chaque appel de la procédure mais sans conviction. Si vous voyez un début de solution à ce problème, vous êtes les bienvenus

    Merci d'avance.

    Amicalement,

    Jean-Marc

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 28
    Points : 18
    Points
    18
    Par défaut
    Petite modification avec des variables globales pour voir, mais sans succès :

    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
     
    Global id_item_liste = 0
    Global parent_id.l = 0
    Global db.l = 1
    Global id_cat.l
    Global niveau.l = 0
    Global dbDB = 1
    Procedure ParcoursCategories2(parent_id)
            OpenDatabase(dbDB, *****)
            If DatabaseQuery(dbDB, "SELECT * FROM categories WHERE parent_categorie_id=" + Str(parent_id) + ";" ) 
                While NextDatabaseRow(dbDB) > 0 
     
                    AddGadgetItem(#Lst_Categories, id_item_liste, GetDatabaseString(1,1) + " - " + GetDatabaseString(1,2),0, niveau)
                    Debug parent_id
                    id_item_liste = id_item_liste + 1
                    ; on récupère l'id de la catégorie
                    id_cat.l = GetDatabaseQuad(1,0)
                    parent_id = id_cat
                    dbDB= dbDB+ 1
                    niveau = niveau +1
                    ParcoursCategories2(parent_id)
                Wend
            EndIf      
     
     
    EndProcedure
    ParcoursCategories2(parent_id)

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 28
    Points : 18
    Points
    18
    Par défaut Je progresse...
    Dernières modifications du code, y a du mieux mais c'est pas encore ça. En fait, il me parcours la première cat, descends dans les sous cat, et ainsi de suite mais il ne "remonte" pas dans l'arborescence...

    Voici le code

    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
     
    Global id_item_liste = 0
    Global parent_id.l = 0
    Global db.l = 1
    Global id_cat.l
    Global niveau.l = 0
    Global dbDB = 1
    Procedure ParcoursCategories2(parent_id)
            dbDB = OpenDatabase(#PB_Any, "***")
            If DatabaseQuery(dbDB, "SELECT * FROM categories WHERE parent_categorie_id=" + Str(parent_id) + ";" ) 
                While NextDatabaseRow(dbDB) > 0 
     
                    AddGadgetItem(#Lst_Categories, id_item_liste, GetDatabaseString(dbDB,1) + " - " + GetDatabaseString(dbDB,2),0, niveau)
     
                    id_item_liste = id_item_liste + 1
                    ; on récupère l'id de la catégorie
                    id_cat.l = GetDatabaseQuad(dbDB,0)
                    parent_id = id_cat
                    dbDB= dbDB + 1
                    niveau = niveau +1
                    ParcoursCategories2(parent_id)
                Wend
            EndIf      
    EndProcedure
    ParcoursCategories2(parent_id)

  7. #7
    Responsable Purebasic

    Avatar de comtois
    Inscrit en
    Avril 2003
    Messages
    1 261
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 1 261
    Points : 9 924
    Points
    9 924
    Billets dans le blog
    8
    Par défaut
    Je ne connais rien aux bases de données, j'ai juste fait cet essai pour découvrir Sqlite.

    Mais à tout hasard, tu es sûr d'avoir défini ta base correctement ? J'ai l'impression que tu as tout mélangé dans une seule table ?

    Si je comprends bien ton problème, tes catégories pourraient être contenues dans une table , les sous catégories dans une autre table ? j'ignore le niveau d'imbrication que peuvent avoir tes catégories ?

    Pour valider l'organisation de ta base de données, tu peux peut-être aussi demander conseil sur le forum base de données ? Je ne connais pas ton parcours, ce conseil est sans doute inutile
    Vous souhaitez participer à la rubrique PureBasic (tutoriels, FAQ, sources) ? Contactez-moi par MP.

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 28
    Points : 18
    Points
    18
    Par défaut
    Bonsoir Comtois et merci de te pencher à nouveau sur mon problème.


    Citation Envoyé par comtois Voir le message
    Mais à tout hasard, tu es sûr d'avoir défini ta base correctement ? J'ai l'impression que tu as tout mélangé dans une seule table ?
    Oui, pas de souci de ce côté là, ma modélisation est bonne

    Citation Envoyé par comtois Voir le message
    Si je comprends bien ton problème, tes catégories pourraient être contenues dans une table , les sous catégories dans une autre table ? j'ignore le niveau d'imbrication que peuvent avoir tes catégories ?
    Non, tout est dans la même table, comme le montre mon schéma du premier post, c'est dans le but justement de pouvoir obtenir un niveau d'imbrication catégories/sous catégories élevé.

    Je pense que le problème doit venir très certainement de mon code, je dois m'y prendre de travers

    Ce n'est pas dramatique, je vais adapter pour me limiter à 3 niveaux d'imbrication ce qui n'est déjà pas si mal et correspond à mon usage (par exemple : Formations informatiques -> Bureautique -> Excel )

    Encore merci de ton aide et bon 14 juillet !

    Amicalement,

    Jean-Marc

  9. #9
    Responsable Purebasic

    Avatar de comtois
    Inscrit en
    Avril 2003
    Messages
    1 261
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 1 261
    Points : 9 924
    Points
    9 924
    Billets dans le blog
    8
    Par défaut
    Je lirai cet article plus tard, mais j'ai l'impression qu'il répond à ton problème ?

    http://sqlpro.developpez.com/cours/s...te-recursives/

    Sinon le feu d'artifice était joli ! comme l'année dernière quoi.

    Bon au lit, demain y'a le défilé !
    Vous souhaitez participer à la rubrique PureBasic (tutoriels, FAQ, sources) ? Contactez-moi par MP.

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 28
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par comtois Voir le message
    Je lirai cet article plus tard, mais j'ai l'impression qu'il répond à ton problème ?

    http://sqlpro.developpez.com/cours/s...te-recursives/

    Sinon le feu d'artifice était joli ! comme l'année dernière quoi.

    Bon au lit, demain y'a le défilé !
    Pas de feu d'artifice pour moi mais un BON GROS début de solution grâce à ton lien, Comtois !

    Effectivement, ça correspond bien à ce que je souhaite faire. Je vais étudier ça en détail

    Merci beaucoup à toi !

    Bons dévs !

    Amicalement,

    Jean-Marc

Discussions similaires

  1. Problème de requêtes SQL imbriquées
    Par lakel dans le forum Schéma
    Réponses: 4
    Dernier message: 12/01/2012, 14h09
  2. Problème de requête SQL avec instruction TRANSFORM
    Par Nosper dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 21/06/2005, 16h15
  3. [SQL] Problème de requête SQL de plus de 8060 caractères ?
    Par webtheque dans le forum MS SQL Server
    Réponses: 13
    Dernier message: 06/04/2005, 15h07
  4. [SQLserver2000][SQLServer CE] problème de requête SQL
    Par JBernn dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 27/01/2005, 09h29
  5. Problème de requète SQL dans un Requery
    Par Keraccess dans le forum Requêtes et SQL.
    Réponses: 7
    Dernier message: 22/10/2004, 14h58

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