Partage
  • Partager sur Facebook
  • Partager sur Twitter

Quel est le problème avec ENUM?

    9 septembre 2010 à 14:34:01

    Bonjour,

    Je vois souvent des topics où des personnes disent qu'il ne faut jamais utiliser enum mais qu'il vaille mieux créer une table et faire la jointure parce que si on a besoin d'ajouter des valeurs c'est pas possible avec enum.

    J'ai essayé mais ça a l'air de marché. Quand on crée un enum ensuite on peut le modifier pour ajouter une valeur.

    Quel est le problème exactement avec ce enum?

    Merci
    • Partager sur Facebook
    • Partager sur Twitter
      9 septembre 2010 à 16:18:35

      Y'a pas de "jamais utiliser ENUM" ou non, faut utiliser ce qui est approprié. Si un champ peut prendre aucune ou une valeur d'un ensemble ENUM est totalement justifié puisqu'il est plus rapide et plus léger qu'une jointure.
      Là où la jointure est utile c'est si ces valeurs se voient associées à d'autres, auquel cas il vaut mieux une jointure avec donc une clé étrangère.
      • Partager sur Facebook
      • Partager sur Twitter
      Ce n'est pas parce que vous ne savez pas vous servir d'un marteau qu'il faut planter des clous au tournevis.
        9 septembre 2010 à 17:23:19

        ENUM est mauvais parce que si on veut ajouter un élément à l'ensemble, il faut modifier la structure de la table (i.e. erreur de conception). ENUM tente de simuler (il le fait très mal) une contrainte CHECK et n'est disponible que pour MySQL.

        Faire une table supplémentaire permet de prévoir les améliorations futures. Exemple simple :
        Tu demandes à tes membres quel est leur animal préféré. Comme tu ne veux pas qu'ils te répondent "papier" ou "dictionnaire", tu utilises ENUM et tu fous 100 animaux dans ledit ENUM. Toutefois, un membre te dit qu'il n'y a pas son animal préféré, l'Axolotl, dans les choix. Qu'est-ce que tu dois faire ? Modifier la structure de ta table pour ajouter l'Axolotl dans les choix. Avec une table supplémentaire, tu ajoutes une nouvelle ligne.

        Rares sont les cas où ENUM est approprié et préférable.
        • Partager sur Facebook
        • Partager sur Twitter
          9 septembre 2010 à 17:29:45

          Pas d'accord avec toi Fayden. Un ENUM peut être très pratique, par exemple dans le cadre d'un BugTracker: 0=Opened, 1=Assigned, 2=Resolved. Dans un Blog: 0=Flash 1=News 2=Brève ... C'est très utile, pour peu de l'utiliser dans les bons cas.
          • Partager sur Facebook
          • Partager sur Twitter
            9 septembre 2010 à 18:21:50

            Même problème qu'avec l'exemple que j'ai donné. Tu fais quoi si tu veux rajouter quelque chose ? Tu modifies la structure de ta table.
            • Partager sur Facebook
            • Partager sur Twitter
              9 septembre 2010 à 19:03:58

              Dans un BugTracker, t'as souvent besoin de rajouter des types ? je peux faire un autre exemple avec un blog: "publied": 0=brouillon,1=non,2=oui. T'auras jamais besoin de rajouter un type.
              • Partager sur Facebook
              • Partager sur Twitter
                9 septembre 2010 à 19:16:36

                Jamais, jusqu'au jour ou tu devras rajouter un type.

                Faut chercher des messages de cintre sournois, il a expliqué plusieurs fois pourquoi c'était naze. Mais je ne me souviens plus s'il parlait uniquement de l'ENUM de mysql ou d'ENUM tout court.
                • Partager sur Facebook
                • Partager sur Twitter
                  9 septembre 2010 à 19:20:24

                  Nami Doc : Si tu veux rajouter Caché ? Supprimé ? Inaccessible à X rang ?
                  Pour le BugTracker, si tu veux rajouter Rejected car la proposition était nulle ?

                  Il faut voir à long terme, il est rare que les choix soient figés pour toujours.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    9 septembre 2010 à 19:31:35

                    Je ne sais pas ce qui relève de l'erreur de conception, mais en tout cas ENUM me semble plus optimisé et ça clarifie la bdd et les requêtes.

                    Qu'est-ce que ça change de devoir ajouter une possibilité à l'ENUM ? ça ne pervertit pas les données déjà entrées, si ?

                    Si on me dit juste que altérer une table c'est une erreur de conception, je pense à une connerie éthique ou philosophique et je n'en tiens pas compte. Après s'il y a une raison fonctionnelle je suis toute ouïe.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      9 septembre 2010 à 19:41:24

                      Fayden > C'est rare mais ça arrive, dans des applications à but (très) précis, comme par exemple une bibliothèque pour tes films.
                      • Partager sur Facebook
                      • Partager sur Twitter
                        9 septembre 2010 à 21:40:33

                        Si tu as besoin d'altérer ta table, c'est souvent parce qu'à la base, tu n'as pas pensé à l'évolution de ton projet. C'est le cas d'ENUM.

                        Je vois pas comment la normalisation ne clarifie pas plus "la BDD et les requêtes" qu'ENUM le fait.
                        • Partager sur Facebook
                        • Partager sur Twitter
                          9 septembre 2010 à 22:48:20

                          Encore une fois je suis pas un pro, mais ça me paraît juste évident :

                          Tu te retrouves rapidement avec des id partout et avec des tables contenant des infos liées à d'autres tables, mais pas dans la même tabe , tu dois faire des JOIN ON en plus du SELECT, désigner les champs par table.champ, mettre des alias, tu as intérêt à préfixer les noms des foreign key ou les noms des tables liées entre elles... ne me dis pas que tout ça n'est pas fait *justement* pour compenser une certaine ambiguïté.

                          Du haut de mon ignorance je peux quand même proclamer que ENUM, c'est forcément plus performant, et c'est plus simple.

                          Quant à l'argument du "c'est souvent parce que tu n'as pas pensé à", ça n'en est pas un : c'est une cause, pas une conséquence. Quelle est la conséquence négative de l'altération d'une table (si il y en a une) ?

                          Parce que je trouve que créer une table à la place d'un ENUM c'est bordélique, et c'est justement une façon de s'en tirer sans réfléchir à l'évolution de son projet plutôt que de se poser deux secondes à imaginer toutes les valeurs possibles d'un champ et à écarter celles qui ne nous intéressent pas dans le présent ou dans un avenir proche.

                          Certaines structures ne peuvent fonctionner qu'avec des jointures pour rester dynamiques, mais d'autres peuvent parfaitement s'en passer AMHA.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            9 septembre 2010 à 23:12:27

                            Comment la normalisation d'une BDD peut être plus bordélique ?

                            Avoir plusieurs tables n'est pas un problème, si tu nommes correctement tes colonnes et tes tables, tu obtiens des requêtes extrêmement claires, une base de données laissant place à l'évolution de cette dernière.

                            Après, côté performance, j'imagine aussi qu'ENUM est plus rapide, mais je n'ai pas de sources pour le prouver. En as-tu ?
                            Côté simplicité, pas d'accord. Y'a rien de compliqué à faire une table de plus, c'est pas plus difficile que de donner le type ENUM à une colonne et ajouter des éléments.

                            L'inconvénient de changer la structure de la table, c'est que c'est long mais surtout, c'est que c'est évitable. Il en résulte ensuite évidemment des conséquences pratiques, comme l'impossibilité d'afficher sur son site, par exemple, tous les éléments d'ENUM. Ça se fait facilement avec une autre table. Tu peux lire ce lien ou bien chercher les posts de Cintre Sournois.

                            Faisons un exemple simple avec deux tables. Reprenons l'exemple du Bug Tracker de Nami Doc.

                            -- Table contenant les bugs
                            CREATE TABLE BGS_BUGS (
                                BGS_ID      SERIAL,
                                BGS_TITLE   VARCHAR(255),
                                BGS_CONTENT TEXT,
                                STT_ID      INTEGER,
                                CONSTRAINT PK_BGS_BUGS_BGS_ID PRIMARY KEY (BGS_ID),
                                CONSTRAINT FK_BGS_STATE FOREIGN KEY (STT_ID) REFERENCES STT_STATES (STT_ID)
                            );
                            
                            -- Tables contenant les états des bugs
                            CREATE TABLE STT_STATES (
                                STT_ID    SERIAL,
                                STT_LABEL VARCHAR(255),
                                CONSTRAINT PK_STT_STATES_STT_ID PRIMARY KEY (STT_ID)
                            );
                            
                            -- Insérons quelques lignes
                            INSERT INTO STT_STATES (STT_LABEL) VALUES ('Opened'), ('Assigned'), ('Resolved');
                            INSERT INTO BGS_BUGS (BGS_TITLE, BGS_CONTENT, STT_ID) VALUES ('bug 1', 'content 1', 1), ('bug 2', 'content 2', 2), ('bug 3', 'content 3', 3), ('bug 4', 'content 4', 1);
                            
                            -- Une simple requête qui affiche l'état de tous les bugs dans la table
                            SELECT B.BGS_ID, B.BGS_TITLE, S.STT_LABEL
                            FROM BGS_BUGS B
                            INNER JOIN STT_STATES S
                                ON B.STT_ID = S.STT_ID
                            ORDER BY B.BGS_ID;
                            


                            C'est difficile de faire plus simple. On veut ajouter un autre état (genre Rejected) ? Pas besoin de modifier la structure de la table, c'est tout simple :
                            INSERT INTO STT_STATES (STT_LABEL) VALUES ('Rejected');
                            
                            -- Changeons le bug #4 pour le nouvel état
                            UPDATE BGS_BUGS SET STT_ID = (SELECT STT_ID FROM STT_STATES WHERE STT_LABEL = 'Rejected') WHERE BGS_ID = 4;
                            


                            Avec ENUM, tu connais la chanson, t'aurais dû modifier la structure de la table.

                            En somme, ENUM n'est pas non plus à bannir, il peut y avoir des cas précis où son utilisation est approprié (genre, si on demande à une personne son sexe, mais encore là il faut faire attention (entreprise, groupe, etc.)), mais souvent (toujours), une nouvelle table est beaucoup plus claire, propre et évolutive.
                            • Partager sur Facebook
                            • Partager sur Twitter
                              9 septembre 2010 à 23:24:46

                              Pour "sexe", ça peut être un booléen.
                              Non mais c'est sûr que dans 95% des cas c'est mieux avec une jointure, mais il reste des cas où c'est pratique. (PS: tes conventions de nommages sont pabel :°)
                              • Partager sur Facebook
                              • Partager sur Twitter
                                9 septembre 2010 à 23:34:45

                                Je me pose exactement la même question que Geoffrey-Zéro, est-ce un problème fonctionnel de rajouter un champ à un enum, est-ce que ça eut faire des problèmes sur la table ou bien c'est juste un problème "théorique"?

                                Parce que le alter se fait très facilement, avec phpmyadmin on a juste à modifier la colonne et y ajouter la valeur.
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  9 septembre 2010 à 23:56:32

                                  Bon je trouve ton code vraiment peu clair mais ça tient du fait que tu adores les acronymes, les capitales et les noms en anglais ;)
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    10 septembre 2010 à 1:29:20

                                    Le seul "acronyme" c'est le nom de la table et c'est justement pour éviter les ambigüités. On voit tout de suite ce que contient telle colonne et à quelle table elle appartient.
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      10 septembre 2010 à 2:49:29

                                      Je sais je fais pareil.

                                      Mais tu ne vas pas me dire qu'un truc du genre B.STT_ID = S.STT_ID est aussi clair que `state`="rejected" .

                                      Déjà, sans connaître tes tables on ne sait pas ce qui correspond à quoi, donc ton code est peu lisible. En suite, tu admettras que bidouiller les noms (parce que c'est de la bidouille) pour lever une ambiguïté prouve l'existence de ladite ambiguïté.

                                      Pour moi ENUM VS jointures c'est ENUM qui l'emporte niveau simplicité et clarté. Pour les performances on gagne peut-être pas grand chose mais sur des tables importantes à mon avis la "double" requête est plus lente ou bouffe plus de ressources qu'un ENUM dans la même table.
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        10 septembre 2010 à 3:08:21

                                        C'est pas parce que tu as de la difficulté à lire le code des autres qu'il est peu lisible. C'est une convention suggérée par SQLPro, si tu ne veux pas l'adopter, c'est pas plus mal.

                                        Ce n'est pas de la bidouille, mais comme tu ne cherches même pas à comprendre, je ne vais pas m'embêter à t'expliquer à nouveau ce que j'ai dit tout au long de ce thread.
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          10 septembre 2010 à 3:29:16

                                          Mais je comprends, tu t'exprimes très bien et je ne remets pas ces conventions en question. C'est juste que je trouve que les jointures n'ont aucun avantage vis à vis d'ENUM, et que des inconvénients, mis à part leur flexibilité. Je reste convaincu que quand on peut utiliser ENUM c'est mieux de le faire. Et quand l'énumération des possibilités est impossible (dynamique), utiliser les jointures.

                                          Pour moi ces techniques répondent à des usages très différents. Une jointure à la place d'un ENUM c'est écraser une mouche avec une enclume. En fait j'étais même étonné de lire qu'on conseillait de faire des jointures à la place, pour moi c'est un contre-sens, et je pense que ça vient du fait que dans d'autres sgbd ENUM n'existe pas et que les gens font comme ils peuvent.

                                          Et effectivement ça sert à rien de reformuler. À moins d'apporter des arguments nouveaux je resterai sur mes positions. (c'est que je suis têtu :p )
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                          Anonyme
                                            17 septembre 2010 à 13:49:54

                                            Et ben, ça rigole pas ici ^^
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              19 septembre 2010 à 0:26:07

                                              ENUM est une magnifique source de bugs, par exemple avec ENUM on peut calculer 1+1=3.

                                              Pour celui qui trouve ça normal, il n'y a aucun problème.

                                              Personnellement je mets un entier, dont le sens est défini par l'application. Au moins, on garde une sémantique correcte : c'est un entier, pas un genre de type alien prompt à t'exploser à la gueule.
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                19 septembre 2010 à 5:32:35

                                                Je ne vois pas l'intérêt de calculer rouge + vert ou true + false...
                                                • Partager sur Facebook
                                                • Partager sur Twitter

                                                Quel est le problème avec ENUM?

                                                × 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