Partage
  • Partager sur Facebook
  • Partager sur Twitter

Théorie : DB relationnelle

clefs etrangeres multiples x) ?

    13 novembre 2010 à 7:30:43

    Bonjour, Bonsoir, enfin je sais plus trop :D

    Après avoir cherché la réponse aux questions existentielles qui me travaillent, à droite à gauche toute la nuit durant, me voila ^^

    Voici mon problème (je prend volontairement un exemple a la con, c'est théorique)

    Imaginons que j'ai une base de donnée relationelle (innoDB par exemble) avec :

    une table ALBUMS avec comme attributs (champs) :
    • ID (key unique, index)
    • title
    • pics
    • people (sur l'album photo)


    une table PICS tel quel :
    • ID (key unique, index)
    • infos
    • camera
    • people (sur la photo)


    et une table PEOPLE tel quel :
    • ID (key unique, index)
    • firstname
    • lastname


    le tout en relation avec une table OBJECTS tel que :
    • ID (key unique, index)
    • author
    • parents
    • childs
    • etc


    Evidement vous imaginez bien que je voudrais pouvoir avoir plusieurs ALBUMS, avec dans chacun plusieurs PICS PEOPLE, etc, chacun de element precedement cité etant egalement un enregistrement de la table OBJECTS (qui sauvegarde les CHILDS et PARENTS, un enfants pouvant avoir un nombre indefini de parents et vis versa)

    Lorsque je veux afficher un des ALBUMS et les infos (PICS, PEOPLE dessus) qui vont avec, quelle solution pour recuperer ces infos avec le moins de requètes possibles ?

    Une jointure me direz-vous.. mais je suis tout de meme obligé de faires plusieurs requetes ?!

    Dans le cas du champs "PICS" de "ALBUMS" suis-je obligé de serialisé les identifiants uniques des photos ? (du genre idphoto1|idphoto2|etc)
    (meme chose pour CHILDS et PARENTS de OBJECTS qui peuvent contenir plus autres objects) .. (dans ce cas je serai donc obligé d'utiliser REGEXP ce qui n'est pas top niveau opti il me semble);

    N'existe t-il pas un systeme miracle de faire tout ca simplement ? avec un stysteme de clef etrangere multi-relationnelement unique (lol) ?
    quelle solution est la plus optimisée?
    un SELECT a heritage multiple (relol) ?

    Bref je m'y perd un peu :p
    J'espere qu'un de vous, zéros specialistes, sera a meme de m'eclairer afin que je puisse retrouver le sommeil ^ ^
    Merci d'avance ..

    Sur ce, bonne nuit, ou bonne journée, ca depends :-°
    • Partager sur Facebook
    • Partager sur Twitter
      13 novembre 2010 à 10:10:28

      Citation : nakwa

      Evidement vous imaginez bien que je voudrais pouvoir avoir plusieurs ALBUMS, avec dans chacun plusieurs PICS PEOPLE, etc, chacun de element precedement cité etant egalement un enregistrement de la table OBJECTS (qui sauvegarde les CHILDS et PARENTS, un enfants pouvant avoir un nombre indefini de parents et vis versa)



      En fait ça se rapproche de la structure d'un CMS où tu as une classe de base (Node) qui peut être dérivée en page web, news, photo, etc et une notion d'arborescence, qui est en fait un graphe puisque les noeuds peuvent avoir plusieurs parents.

      J'avais fait un système comme ceci, de la façon suivante :

      - table nodes (node_id, attributs)
      - table relations (parent_id FK sur nodes, child_id FK sur nodes, attributs)

      C'est la manière la plus simple

      Il faut absolument éviter de mettre des listes d'ids séparés par des "|" dans les colonnes, c'est inexploitable. Tu as une BDD, utilise des tables !

      Maintenant, pour fourrer dans "nodes" tous tes divers objets, il faut faire un peu d'héritage en SQL (regarde sur developpez.net chez sqlpro) et choisir ta stratégie...
      • Partager sur Facebook
      • Partager sur Twitter
      Anonyme
        13 novembre 2010 à 14:29:22

        Pourquoi faire une table OBJECTS ?
        • Partager sur Facebook
        • Partager sur Twitter
          13 novembre 2010 à 14:39:22

          Ben j'avais fait une table "nodes" car je voulais que tout node puisse avoir des enfants et des parents (par exemple un Node "gallery" contient d'autres "gallery", des "articles", des "photos" etc) avec un seul code pour gérer la pseudo-arborescence, déplacer les machins, etc. Avec une table "nodes" + table "relations" (parent,enfant) ça fonctionne très bien. Ca ressemble à une arborescence de fichier linux avec des hardlinks.
          • Partager sur Facebook
          • Partager sur Twitter
          Anonyme
            13 novembre 2010 à 14:43:52

            C'est quoi les règles de gestion ?

            1) Dans un ALBUM il a plusieurs PICT ?
            2) Dans une PICT il a plusieurs PEOPLE ?
            3) Dans un ALBUM il a plusieurs PEOPLE ?

            Rayez la mention inutile, ou ajoutez-en de nouvelles (utiles).
            • Partager sur Facebook
            • Partager sur Twitter
              13 novembre 2010 à 17:19:41

              Bonsoir,

              merci pour vos reponses a tous !

              @Lord Casque Noir > tu me rassures sur ce que je veux faire ;)
              par contre je cerne pas bien le coup de l'heritage mysql .. c'est simplement des relations ? ou il existe bel et bien une notion d'heritage sql que je ne connais pas ?

              Citation : Lord Casque Noir

              J'avais fait un système comme ceci, de la façon suivante :

              - table nodes (node_id, attributs)
              - table relations (parent_id FK sur nodes, child_id FK sur nodes, attributs)



              En gros si je comprend bien c'est un peu comparable a un system d'acl avec des "groups" ?
              pour reprendre mon exemple tu veux dire stocker dans relation une entree pour chaque ID_PICS lié a un album ?
              mais pour faire ce que je veux, je vais forcement me retrouver avec une table RELATION_CHILDS RELATION_PARENTS ?
              et eventuellement un table referencant des index particuliers ?

              @cintre sournois > je voudrais effectivement que tes trois affirmation soit des cas possibles! a savoir qu'une entree des la tables ALBUMS (un album donc) puisse contenir differentes photos (entrees de la table PICS) et qu'on puisse signaler la presence de differentes personnes (PEOPLE), aussi bien sur une photos (PICS) precise que sur un album...

              j'ai cherché mais je ne parviens pas a trouver de reponse claire, connaitrais-tu un cours, un tutos, ou au pire un bouqin sur ce genre de structuration d'une bdd? (j'avais deja regardé sur devellopez, sans vraiment trouver mon bonheur, sauf a enchainer des pavés ... )

              D'autres pistes ?
              • Partager sur Facebook
              • Partager sur Twitter
              Anonyme
                13 novembre 2010 à 18:18:57

                T'as trois tables:

                PICT
                ALBUM
                PEOPLE

                Dans un ALBUM y a des PICT, ajout d'une table (PK soulignée, FK italique) :

                ALBUM_PICT (alb_id, pict_id)

                Dans une PICT y a des PEOPLE :

                PICT_PEOPLE (pict_id, people_id)

                Celle là, je voit pas l'intérêt, mais soit: Dans un ALBUM y a des PEOPLE :

                ALBUM_PEOPLE (alb_id, people_id)


                Y a pas plus simple !
                • Partager sur Facebook
                • Partager sur Twitter
                  13 novembre 2010 à 18:28:03

                  Ouais mais dans un album il y a aussi des albums non ? Vu que l'OP veut relier tout à tout, il va se retrouver avec n² tables.

                  L'avantage de la table "relation" entre lignes d'une table "nodes" est que tu peux relier tout avec tout. Evidemment, tu peux aussi relier tout avec n'importe quoi...
                  • Partager sur Facebook
                  • Partager sur Twitter
                    13 novembre 2010 à 18:41:32

                    des albums dans des albums ?
                    a la rigueur que des pics soit contenu dans plusieurs albums, mais un album dans un album, je vois pas l'interet?
                    • Partager sur Facebook
                    • Partager sur Twitter
                      13 novembre 2010 à 19:30:45

                      Comme aux débuts de Picasaweb (la raison pour laquelle ce soft était inutilisable) : t'as droit qu'à un seul niveau, donc tu mets tout dans la racine, impossible de faire une organisation correcte...

                      Racine :

                      - album : vacances à cancun
                      - album : déculassage de la BX à momo
                      - album : chat de ma copine qui montre son anus
                      - album : mariage

                      ça a un petit côté grolandais...
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Anonyme
                        13 novembre 2010 à 19:51:28

                        Si un album a des sous albums, c'est une table à part.
                        SOUS_ALBUM (alb_parent, alb_enfant)

                        Il n'y a aucune raison de tout mettre dans une table.
                        Une image n'a pas de sous-image, les people n'ont pas non plus de sous-people.
                        • Partager sur Facebook
                        • Partager sur Twitter
                          14 novembre 2010 à 12:12:11

                          l'idée de cintre sournois me semble plus prometteuse nan ?
                          quel fonctionnalité perd t on en faisant comme ca plutôt qu'avec la méthode de casque noir ?

                          ps : j'adore ton exemple casque noir :p
                          • Partager sur Facebook
                          • Partager sur Twitter
                          Anonyme
                            14 novembre 2010 à 12:27:55

                            Citation : luckyboss1

                            quel fonctionnalité perd t on en faisant comme ca plutôt qu'avec la méthode de casque noir ?


                            Je n'ai pas le temps de faire une démo, mais on ne perd pas de fonctionnalité. Au contraire.
                            C'est un design beaucoup plus "naturel" et évolutif.
                            • Partager sur Facebook
                            • Partager sur Twitter
                              14 novembre 2010 à 12:52:22

                              D'accord, c'est bien ce qu'il me semblait.

                              Mais alors y a t il un interet a faire une méthode plus complexe ?
                              • Partager sur Facebook
                              • Partager sur Twitter
                                14 novembre 2010 à 15:15:03

                                bonjour,

                                merci pour vos idées et vos propositions ;)

                                Citation

                                En fait ça se rapproche de la structure d'un CMS où tu as une classe de base (Node) qui peut être dérivée en page web, news, photo, etc et une notion d'arborescence, qui est en fait un graphe puisque les noeuds peuvent avoir plusieurs parents.



                                C'est a peu près ca ;)

                                donc après reflexion je pense que je vais faire comme ca :

                                TABLE OBJECTS (ou NODE)
                                • - ID (PK, FK)
                                • - type (albums, pics, etc)
                                • - author, etc


                                TABLE RELATIONS
                                • - ID parents (FK)
                                • - ID childs (FK)


                                TABLE ALBUMS
                                • - ID (PK, FK)
                                • - title, etc


                                TABLE PICS
                                • - ID (PK, FK)
                                • - legende, etc


                                TABLE PEOPLE
                                • - ID (PK, FK)
                                • - name, etc


                                Ca peut paraitre tordu mais c'est ce qui me semble le plus souple et evolutifs :)
                                Exemple : Oh, bah tiens, je vais creer un table FORUMS, une table CATEGORIES, et une table TOPICS ^^
                                Ca parait cohérent, non?

                                EDIT :

                                Arretez moi si je me trompe, mais étant donnée qu'il peut y avoir plusieurs childs pour plusieurs parents, ma table RELATION qui a pour fields CHILD et PARENT ne peut contenir aucune clef primaire, ni unique, ni index.
                                Je voudrais tout de meme créer une relation entre CHILD et la clef primaire OBJECT.ID.
                                Dans les relations il y a deux choses : Relations Internes et FOREIGN KEY ..

                                J'ai relié mes champs relations.child et relations.parent a objects.id, mais d'habitude j'utilise seulement des FK.. Quelles differences entre les deux ?
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  18 novembre 2010 à 18:44:43

                                  Citation : nakwa

                                  Arretez moi si je me trompe, mais étant donnée qu'il peut y avoir plusieurs childs pour plusieurs parents, ma table RELATION qui a pour fields CHILD et PARENT ne peut contenir aucune clef primaire



                                  la clé primaire est (parent_id,child_id) sauf si tu veux enregistrer plusieurs fois la même relation entre les mêmes éléments, ce qui ne présente pas grand intérêt...
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    19 novembre 2010 à 11:01:21

                                    Citation : nakwa


                                    donc après reflexion je pense que je vais faire comme ca :

                                    TABLE OBJECTS (ou NODE)

                                    • - ID (PK, FK)
                                    • - type (albums, pics, etc)
                                    • - author, etc



                                    Je ne suis pas un spécialiste (moi aussi je commence avec les BDD type relationnelle ;) ) mais il me semble que si tu veux faire une vrai BDD relationnelle, il ne faut pas de champs "type" dans ta BDD (une clef étrangère ne doit pointer que vers un seul champs d'une seule table)

                                    Il faut toujours :
                                    • créer un champs ID(PK) par table (non relationelle) => correction !
                                    • qu'il n'y ait pas de doublons
                                    • différencier la description des éléments de leurs relations
                                    • déclarer correctement les contraintes et les types des champs (n'importe quelle personne qui reprend ta BDD doit pourvoir l'utiliser juste en analysant sa structure)

                                    Les contraintes permettent d'éviter qu'il y ai de mauvaise manipulations (ajouts/suppressions/modifications d'éléments) dans la BDD,


                                    Donc perso, je ferais comme ça :


                                    TABLE PERSON :
                                    • PERSON_ID (PK) => correction !
                                    • PERSON_NAME
                                    • PERSON_ATTRIBUT1
                                    • PERSON_ATTRIBUT...


                                    TABLE PICS:
                                    • PICS_ID (PK)
                                    • PICS_NAME
                                    • PICS_ATTRIBUT1
                                    • PICS_ATTRIBUT...


                                    TABLE ALBUM:
                                    • ALBUM_ID (PK)
                                    • ALBUM_NAME
                                    • ALBUM_ATTRIBUT1
                                    • ALBUM_ATTRIBUT...



                                    TABLE PERSON_IN_PICS (relation):
                                    • PERSON_IN_PICS_ID (PK) => correction !
                                    • PICS_ID (FK)
                                    • PERSON_ID (FK)

                                    PK(PICS_ID, PERSON_ID) => correction !


                                    TABLE PICS_IN_ALBUM (relation):
                                    • PICS_IN_ALBUM_ID (PK) => correction !
                                    • ALBUM_ID (FK)
                                    • PICS_ID (FK)

                                    PK(ALBUM_ID, PICS_ID) => correction !


                                    TABLE ALBUM_IN_ALBUM (relation):
                                    • ALBUM_IN_ALBUM_ID (PK) => correction !
                                    • ALBUM_ID_PARENT (FK)
                                    • ALBUM_ID_CHILD (FK)

                                    PK(ALBUM_ID_PARENT, ALBUM_ID_CHILD) => correction !


                                    => Donc avec cette méthode tu dois pouvoir retrouver facilement n'importe quels éléments avec leurs relations.

                                    Donc si on veut afficher les personnes qui sont dans un album, il faut faire quoi comme requête (j'en suis ici pour mon apprentissage ;) )?
                                    SELECT ALBUM.ALBUM_NAME, PERSON.PERSON_NAME
                                    FROM ????
                                    INNER JOIN ????
                                    ON ????
                                    WHERE ALBUM.ALBUM_NAME = 'vacances2010'
                                    




                                    Attention, aux noms des champs de tes tables : je te conseille de toujours mettre le nom de la table dans le nom du champs qui sont susceptibles d'être utilisé pour une clef étrangère car après ça devient vite le bordel lorsqu'on fait des tables de relations


                                    Aussi, voici un cours que je trouve pas mal (pour apprendre les bases, je le trouve mieux fait que ce qu'il y a sur www.developpez.com) : http://cerig.efpg.inpg.fr/tutoriel/bas [...] /sommaire.htm

                                    Cours pour la gestion des contraintes : http://sqlpro.developpez.com/cours/sql [...] page=sommaire
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Anonyme
                                      19 novembre 2010 à 12:25:07

                                      Les colonnes "ID" dans les tables dites "de jointure" ou "d'association", comme PERSON_IN_PICS sont totalement inutile !_!

                                      La clé primaire est composée de deux colonnes (qui sont elles même des clés étrangères). Les deux colonnes garantissent les propriétés d'unicité et d'irréductibilité d'une clé primaire.

                                      Tu remarqueras que j'ai déjà proposé cette structure, quelques posts plus hauts.

                                      Mais les notions de "objects", "childs", "nodes" sont plus "hype", "kikoolol", nawak fera surrement cela.
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        19 novembre 2010 à 13:27:06

                                        Citation : Cintre Sournois

                                        Les colonnes "ID" dans les tables dites "de jointure" ou "d'association", comme PERSON_IN_PICS sont totalement inutile !_!

                                        La clé primaire est composée de deux colonnes (qui sont elles même des clés étrangères). Les deux colonnes garantissent les propriétés d'unicité et d'irréductibilité d'une clé primaire.


                                        => j'ai fait les corrections


                                        Citation : Cintre Sournois


                                        Tu remarqueras que j'ai déjà proposé cette structure, quelques posts plus hauts.


                                        => effectivement, j'ai pas les yeux en face des trous :/



                                        Citation : Cintre Sournois


                                        Mais les notions de "objects", "childs", "nodes" sont plus "hype", "kikoolol", nawak fera surrement cela.


                                        => tu peux me dire l'avantages de cette methode car je n'en vois pas (c'est moins naturel => donc faut se triturer un peu plus le cerveau pour l'utiliser). C'est peut-être plus facile à maintenir ou à débugger ou recherches plus rapides ?


                                        Remarque : dans la description de BDD de nakwa, il me semble que OBJECTS.type devrait être un INTERGER (qu'on appelerait TYPE_ID) et qu'il faut créer une table TYPE(TYPE_ID, TYPE_NAME) afin d'accélérer la vitesse des recherches, non (c'est plus facile de trier un INTERGER qu'une chaine de caractère) ?


                                        Quelqu'un peut donner les requêtes SQL qu'il faut exécuter pour lister les personnes qui sont dans un album nommé (pour les deux type de structure) ?
                                        Même question mais pour lister les personnes qui sont dans un album nommé qui a plusieurs sous-albums
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          21 novembre 2010 à 19:25:14

                                          Je vais pour une fois être en désaccord avec cintre sournois : pour un bidule de type CMS où tu as un arbre (ou un graphe) de machins (dossiers, articles, albums, galeries photo, photos, etc) je préfère de loin le faire à la kikoolol : table "nodes", table "relation" et héritage pour les divers types de noeuds. En effet je ne vois pas trop l'intérêt d'une structure qui créé n^2 tables de relations quand on a n types de noeuds.

                                          Dans ce cas, pour répondre à ta question en gras :

                                          DROP TABLE nodes CASCADE;
                                          DROP TABLE relations CASCADE;
                                          
                                          CREATE TABLE nodes ( 
                                            node_id     SERIAL PRIMARY KEY, 
                                            node_title  TEXT, 
                                            node_type   TEXT 
                                          );
                                          
                                          CREATE TABLE relations( 
                                            parent_id INTEGER NOT NULL REFERENCES nodes( node_id ) ON DELETE CASCADE, 
                                            child_id INTEGER NOT NULL REFERENCES nodes( node_id ) ON DELETE CASCADE,
                                            PRIMARY KEY( parent_id, child_id )
                                          );
                                          
                                          INSERT INTO nodes (node_title,node_type) VALUES 
                                            ('dossier 1','dossier'),
                                            ('dossier 2','dossier'),
                                            ('jean','personne'),
                                            ('pierre','personne'),
                                            ('paul','personne');
                                            
                                          SELECT * FROM nodes;
                                          
                                           node_id | node_title | node_type 
                                          ---------+------------+-----------
                                                 1 | dossier 1  | dossier
                                                 2 | dossier 2  | dossier
                                                 3 | jean       | personne
                                                 4 | pierre     | personne
                                                 5 | paul       | personne
                                          
                                          INSERT INTO relations (parent_id, child_id) VALUES (1,2),(1,3),(1,4),(2,4),(2,5);
                                          SELECT p.*, c.* FROM relations r JOIN nodes p ON p.node_id=r.parent_id JOIN nodes c ON c.node_id=r.child_id;
                                          
                                              node_id | node_title | node_type | node_id | node_title | node_type 
                                          ---------+------------+-----------+---------+------------+-----------
                                                 1 | dossier 1  | dossier   |       2 | dossier 2  | dossier
                                                 1 | dossier 1  | dossier   |       3 | jean       | personne
                                                 1 | dossier 1  | dossier   |       4 | pierre     | personne
                                                 2 | dossier 2  | dossier   |       4 | pierre     | personne
                                                 2 | dossier 2  | dossier   |       5 | paul       | personne
                                          
                                          -- enfants du 'dossier 1' de type 'personne'
                                          SELECT n.* FROM relations r JOIN nodes n ON n.node_id=r.child_id WHERE r.parent_id = 1 AND n.node_type = 'personne'; 
                                           
                                           node_id | node_title | node_type 
                                          ---------+------------+-----------
                                                 3 | jean       | personne
                                                 4 | pierre     | personne
                                          
                                          -- la même, en récursif (le dossier 2 est contenu dans le dossier 1)
                                          WITH RECURSIVE node_search(node_id) AS (
                                            SELECT node_id FROM nodes WHERE node_id = 1
                                            UNION
                                            SELECT r.child_id
                                                  FROM node_search n JOIN relations r ON (n.node_id=r.parent_id)
                                          )
                                          SELECT n.* FROM node_search s JOIN nodes n ON (n.node_id=s.node_id) WHERE n.node_type='personne';
                                          
                                          node_id | node_title | node_type 
                                          ---------+------------+-----------
                                                 3 | jean       | personne
                                                 4 | pierre     | personne
                                                 5 | paul       | personne
                                          
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            22 novembre 2010 à 11:55:51

                                            ok, merci pour les infos ;)
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              22 novembre 2010 à 21:14:29

                                              Je ne crois pas que les notions de node, childs, relations, etc, soient "kikoukissloltmtc" ou quoi que ce soit d'autre, car, cas theoriques de ce topic mis a part, ce que je "m'amuse" a faire c'est un generateur de "modules", du genre albums, images, user, ou ce que tu veux.

                                              ..c'est donc justement parceque que les fichiers, les class, les tables, les vues correspondantes a chaque modules sont générée dynamiquement qu'il me semble que je n'ai pas d'autre choix que d'utiliser cette organisation avec des nodes, etc.

                                              (je ne vais pas creer 50000 tables de relations a chaque fois qu'un utilisateur "link" un module a un autre...)

                                              bref, en tout cas merci a tous pour vos reponses, j'y vois plus clair.
                                              • Partager sur Facebook
                                              • Partager sur Twitter

                                              Théorie : DB relationnelle

                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                              • Editeur
                                              • Markdown