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

Schéma Discussion :

Comment caracteriser l'heritage avec MySQL Workbench ?


Sujet :

Schéma

  1. #1
    Candidat au Club
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Octobre 2011
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2011
    Messages : 3
    Points : 4
    Points
    4
    Par défaut Comment caracteriser l'heritage avec MySQL Workbench ?
    Bonjour,

    Je modelise une application de gestion des annonces dans une localité bien définie.
    L'annonce n'est pas categorisée et donc concerne tout type d'annonce que l'utilisateur pourra décider de publier. (Auto, Moto, Immobilier, Bijoux, Informatique, Electronique....).

    Voici quelques grandes lignes sur lesquelles je me suis butté.

    1. Un Utilisateur peut mettre Une ou Plusieurs Annonce.
    2. Une Annonce concerne Un et Un-Seul Produit a la fois.
    3. A chaque produit est lié une seule Catégorie(Auto,Moto,Immobilier...)

    Ce qui peut se modéliser par:
    Utilisateur (0,n) -------------- (1,1) Annonce (1,1) ----------- (1,1) Produit
    Produit (1,1) ----------------- (0,n) Categorie.


    Alors dans une annonce non categorisée au depart, toute catégorie d'objet peut faire l'objet d'une annonce.
    Dans la relation : Produit (1,1) ----------------- (0,n) Categorie, on voit bien qu'il faut différencier les catégories. Par exemple une Auto a pour caracteristique le Type de Carburant (Diesel, Hybride, Essence, Gasoil), le Nombre de Chevaux, le Nombre de Cylindre.... alors que pour un Immobilier on a par exemple : le Type (Maison, Appartement, Chambre, Studio...).

    Au regard de tout ceci, on convient donc qu'on ne peut pas a priori se contenter d'une seul entité pour contenir nos différentes catégories. Car il serait fastidieux de devoir gerer toutes les caracteristiques sur un seul tuplet.

    Il est donc imperatif, pour chacune des Catégories, de créer une entité qui lui est propre avec ses caracteristiques. Mais la encore il y a un probleme. Si l'application est en production et que l'on décide d'ajouter une catégorie, il va falloir lui créer une entité dans la base de données et également créer son formulaire... ca complique les choses.

    Donc pour tenter de résoudre ce probleme de facon plus simple et souple, j'ai pensé a faire de l'héritage mais alors comment représenter l'héritage avec MySQL Workbench ?

    Ou alors, si quelqu'un a deja travaillé sur un projet similaire, comment l'a t-il abordé ? et comment a t-il résolu le probleme ?

    Merci.

  2. #2
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Il y a déjà eu des cas similaires de traités sur ce forum.

    Sur le principe de l'héritage de données, voir l'article de SQLPro.

    MCD :
    A -(1,1)----hériter_de----0,1- B

    Tables :
    B (B_id, [colonnes communes à tous les B])
    A (A_id_B, [colonnes spécifiques à A])
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  3. #3
    Candidat au Club
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Octobre 2011
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2011
    Messages : 3
    Points : 4
    Points
    4
    Par défaut
    Bonjour @CinePhi,

    Merci pour ta reponse.

    En suivant le lien que tu as donne ci-dessus, je suis tombe sur l'approche de l'heritage conditionnel, je crois que c'est le cas qui me convient le plus dans cette situation.

    Mais si je souhaite un heritage conditionnel avec Ajout de Colonne dans la table Mere (Categorie dans mon cas). Cf. image attachee ci-dessous.

    Comment est ce que je pourrai ecrire les TRIGGERS pour differencier les differentes categories pendant l'insertion ?
    Images attachées Images attachées  

  4. #4
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Bonsoir gkant,


    Reprenons votre diagramme :
    Citation Envoyé par gkant Voir le message
    Vous n’avez sans doute pas fait attention à la nature des associations entre les types d’entités (tables dans le cas de MySQL Workbench). Littéralement on vous lit ainsi :
    Une catégories (notons que vous imposez le pluriel et qu’il faudra renommer toutes les tables au singulier) est composée de 1 à N véhicules et de 1 à N immobiliers ;

    Un véhicules est composé de 1 à N autos et de 1 à N motos ;

    Un immobiliers est composé de 1à N appartements et de 1à N studios et de 1 à N maisons.
    Alors qu’il faut lire :
    Un véhicule est une auto ou une moto ;

    Un Immobilier (que j’ai renommé pour ma part en LOGEMENT pour éviter de loucher) est un appartement ou un studio ou une maison.
    La représentation attendue est la suivante, par exemple pour les relations entre VEHICULE et ses sous-types :



    A cet effet, la relation entre le surtype VEHICULE et le sous-type AUTO passe par la mise en œuvre d’une relation identifiante (Identifying relationship) 1:1 :



    Et pour signifier que seuls certains véhicules sont des autos, on remplace 1 par 0,1 côté AUTO comme ci-dessus. Pour cela, on double-clique sur le lien entre VEHICULE et AUTO pour faire apparaître l’onglet qui va bien (« Foreign key ») ;il ne reste plus qu’à décocher la case « Mandatory » :



    Citation Envoyé par gkant Voir le message
    Il est donc imperatif, pour chacune des Catégories, de créer une entité qui lui est propre avec ses caracteristiques. Mais la encore il y a un probleme. Si l'application est en production et que l'on décide d'ajouter une catégorie, il va falloir lui créer une entité dans la base de données...
    De toute façon, qu’il s’agisse d’une auto, d’un logement, d’un bijou ou d’un équipement informatique, en partant sur l’héritage, chaque type de produit fera l’objet d’un sous-type, mais ce produit sera accessible via sa clé (ProduitId). Cela vous gêne-t-il ?

    La notion de catégorie fait double emploi avec l’héritage, à mon sens elle peut disparaître. On a des produits qui se déclinent en véhicules, logements, etc. :



    Si l’utilisateur (au sens large) s’intéresse aux motos, vous pouvez définir une vue à cet effet, qui soit la jointure sur ProduitId des tables PRODUIT, VEHICULE, MOTO et il aura ainsi accès de façon simple à l’ensemble des composants (logés à tous les étages...) d’une moto en particulier (et sans le nombre de portes !)


    Citation Envoyé par gkant Voir le message
    Comment est ce que je pourrai ecrire les TRIGGERS pour differencier les differentes categories pendant l'insertion ?
    Tout dépend du SGBD. Si vous utilisez MS SQL SERVER je pourrai vous aider, sinon il vous faudra aller à la pêche dans les forums dédiés.
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  5. #5
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut Vues et triggers
    En complément :

    Citation Envoyé par fsmrel Voir le message
    Si l’utilisateur (au sens large) s’intéresse aux motos, vous pouvez définir une vue à cet effet, qui soit la jointure sur ProduitId des tables PRODUIT, VEHICULE, MOTO et il aura ainsi accès de façon simple à l’ensemble des composants (logés à tous les étages...) d’une moto en particulier.
    Partons des définitions suivantes pour les tables :

    Code SQL : 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
    CREATE TABLE PRODUIT
    (       ProduitId          INT          NOT NULL
          , Observations       VARCHAR(64)  NOT NULL
        , CONSTRAINT PRODUIT_PK PRIMARY KEY (ProduitId)) 
    ; 
    CREATE TABLE VEHICULE
    (       ProduitId          INT          NOT NULL
          , NbCylindres        INT          NOT NULL
          , NbChevaux          INT          NOT NULL
        , CONSTRAINT VEHICULE_PK PRIMARY KEY (ProduitId)
        , CONSTRAINT VEHICULE_PRODUIT_FK FOREIGN KEY (ProduitId)
              REFERENCES PRODUIT ON DELETE CASCADE)
    ;
    CREATE TABLE AUTOMOBILE
    (       ProduitId          INT          NOT NULL
          , NbPortes           INT          NOT NULL
        , CONSTRAINT AUTOMOBILE_PK PRIMARY KEY (ProduitId)
        , CONSTRAINT AUTOMOBILE_VEHICULE_FK FOREIGN KEY (ProduitId)
              REFERENCES VEHICULE ON DELETE CASCADE)
    ;
    CREATE TABLE MOTO
    (       ProduitId          INT          NOT NULL
        , CONSTRAINT MOTO_PK PRIMARY KEY (ProduitId)
        , CONSTRAINT MOTO_VEHICULE_FK FOREIGN KEY (ProduitId)
              REFERENCES VEHICULE ON DELETE CASCADE) 
    ;
    CREATE TABLE LOGEMENT
    (       ProduitId          INT          NOT NULL
          , Superficie         INT          NOT NULL
        , CONSTRAINT LOGEMENT_PK PRIMARY KEY (ProduitId)
        , CONSTRAINT LOGEMENT_PRODUIT_FK FOREIGN KEY (ProduitId)
              REFERENCES PRODUIT ON DELETE CASCADE) 
    ;

    Supposons que vous vouliez créer les données pour une automobile. Il y a 3 tables à mettre à jour : PRODUIT, VEHICULE et AUTOMOBILE. Pour vous épargner de la peine, vous pouvez directement mettre à jour la vue VOITURE ainsi définie :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    CREATE VIEW VOITURE (ProduitId, NbCylindres, NbChevaux, NbPortes, Observations)
    AS
        SELECT x.ProduitId, NbCylindres, NbChevaux, NbPortes, Observations
        FROM   PRODUIT AS x 
                   JOIN VEHICULE AS y ON x.ProduitId = y.ProduitId 
                   JOIN AUTOMOBILE AS z ON x.ProduitId = z.ProduitId
    ;

    Mais à ce jour, quasiment tous les SGBD répugnent — à tort ! — à mettre à jour une vue qui comporte des jointures : on est donc obligé de mettre en œuvre des triggers associés à la vue pour que les choses se passent bien.

    Un trigger (MS SQL Server en l’occurrence) pour insérer les données d’une voiture (ou plusieurs) :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    CREATE TRIGGER VOITURE_TRIGGER_INSERT ON VOITURE INSTEAD OF INSERT AS
     
    INSERT INTO PRODUIT (ProduitId, Observations)
        SELECT ProduitId, Observations
        FROM   INSERTED
    ;
    INSERT INTO VEHICULE (ProduitId, NbCylindres, NbChevaux)
        SELECT ProduitId, NbCylindres, NbChevaux
        FROM   INSERTED
    ;
    INSERT INTO AUTOMOBILE (ProduitId, NbPortes)
        SELECT ProduitId, NbPortes
        FROM   INSERTED
    ;

    Un trigger pour modifier les données d’une voiture (ou plusieurs) :

    Code SQL : 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
    CREATE TRIGGER VOITURE_TRIGGER_UPDATE ON VOITURE INSTEAD OF UPDATE AS
     
    IF UPDATE (ProduitId)  
         BEGIN
            RAISERROR ('On ne touche pas aux clés primaires !', 16, 1)
            ROLLBACK TRAN
            RETURN
        END
    ;
    IF UPDATE (Observations)  
        BEGIN
            UPDATE PRODUIT 
                SET Observations = (SELECT Observations 
                                    FROM   INSERTED
                                    WHERE  PRODUIT.ProduitId = INSERTED.ProduitId
                                   )
                                    WHERE  ProduitId IN (SELECT PRODUIT.ProduitId 
                                                         FROM   PRODUIT JOIN INSERTED
                                                         ON PRODUIT.ProduitId = INSERTED.ProduitId)
        END
    ;
    IF UPDATE (NbCylindres)  
        BEGIN
            UPDATE VEHICULE 
                SET NbCylindres = (SELECT NbCylindres 
                                   FROM   INSERTED
                                   WHERE  VEHICULE.ProduitId = INSERTED.ProduitId
                                  )
                                   WHERE  ProduitId IN (SELECT VEHICULE.ProduitId 
                                                        FROM   VEHICULE JOIN INSERTED
                                                        ON VEHICULE.ProduitId = INSERTED.ProduitId)
        END
    ;
    IF UPDATE (NbChevaux)  
        BEGIN
            UPDATE VEHICULE 
                SET NbChevaux = (SELECT NbChevaux 
                                 FROM   INSERTED
                                 WHERE  VEHICULE.ProduitId = INSERTED.ProduitId
                                )
                                 WHERE  ProduitId IN (SELECT VEHICULE.ProduitId 
                                                      FROM   VEHICULE JOIN INSERTED
                                                      ON VEHICULE.ProduitId = INSERTED.ProduitId)
        END
    ;
    IF UPDATE (NbPortes)  
        BEGIN
            UPDATE AUTOMOBILE 
                SET NbPortes = (SELECT NbPortes 
                                FROM   INSERTED
                                WHERE  AUTOMOBILE.ProduitId = INSERTED.ProduitId
                               )
                                WHERE  ProduitId IN (SELECT AUTOMOBILE.ProduitId 
                                                     FROM   AUTOMOBILE JOIN INSERTED
                                                     ON AUTOMOBILE.ProduitId = INSERTED.ProduitId)
        END
    ;

    Un trigger pour supprimer une voiture (ou plusieurs) :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CREATE TRIGGER VOITURE_TRIGGER_DELETE ON VOITURE INSTEAD OF DELETE AS
     
        DELETE FROM PRODUIT
               WHERE ProduitId IN (SELECT ProduitId
                                   FROM   DELETED) 
    ;
    Ce trigger est moins bavard que les précédents, mais efficace ! En effet, si on supprime au niveau PRODUIT, par le jeu de l’effet CASCADE déclaré dans les contraintes référentielles VEHICULE_PRODUIT_FK et AUTOMOBILE_VEHICULE_FK, la suppression est propagée dans les tables VEHICULE et AUTOMOBILE. Cette façon de faire est justifiée par le fait qu’on est dans un contexte d’héritage et que conceptuellement parlant, VOITURE est à considérer comme un produit à part entière.

    Dans tout cela, le trigger pour exclusion devient inutile.

    Dans ce genre de contexte, il est préférable d’interdire les mises à jour directes des tables, donc de supprimer les droits correspondants et n’autoriser que la mise à jour de la « table » VOITURE (même principe pour les motos, les appartements, etc.)


    Un début de jeu d’essai (toujours MS SQL Server) :

    Code SQL : 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
    DECLARE @CHAR AS TABLE
    (
            ProduitId          INT          NOT NULL
          , NbCylindres        INT          NOT NULL
          , NbChevaux          INT          NOT NULL
          , NbPortes           INT          NOT NULL
          , Observations       VARCHAR(64)  NOT NULL
        , PRIMARY KEY (ProduitId)
    ) ;
     
    INSERT INTO @CHAR (ProduitId, NbCylindres, NbChevaux, NbPortes, Observations) VALUES (1, 7, 8, 5, 'Pas mal') ;
    INSERT INTO @CHAR (ProduitId, NbCylindres, NbChevaux, NbPortes, Observations) VALUES (2, 7, 8, 5, 'Pas cher') ;
    INSERT INTO @CHAR (ProduitId, NbCylindres, NbChevaux, NbPortes, Observations) VALUES (3, 5, 6, 3, 'Mouais...') ;
    INSERT INTO @CHAR (ProduitId, NbCylindres, NbChevaux, NbPortes, Observations) VALUES (4, 5, 6, 1, 'Bof...') ;
     
    INSERT INTO VOITURE (ProduitId, NbCylindres, NbChevaux, NbPortes, Observations)
        SELECT ProduitId, NbCylindres, NbChevaux, NbPortes, Observations
        FROM   @CHAR
    ;
    SELECT '' AS 'PRODUIT', * FROM   PRODUIT ;
    SELECT '' AS 'VEHICULE', * FROM   VEHICULE ;
    SELECT '' AS 'AUTOMOBILE', * FROM   AUTOMOBILE ;
     
    UPDATE VOITURE 
        SET   NbPortes = NbPortes + 1
            , Observations = 'Vendu'
            , NbCylindres = NbCylindres + 1
            , NbChevaux = NbChevaux + 1
        WHERE ProduitId = 2
    ;
    UPDATE VOITURE 
        SET NbPortes = NbPortes + 1
     ;
    SELECT '' AS 'PRODUIT', * FROM   PRODUIT ;
    SELECT '' AS 'VEHICULE', * FROM   VEHICULE ;
    SELECT '' AS 'AUTOMOBILE', * FROM   AUTOMOBILE ;
     
    DELETE FROM VOITURE
        WHERE NbPortes < 5
    ;
    SELECT '' AS 'PRODUIT', * FROM   PRODUIT ;
    SELECT '' AS 'VEHICULE', * FROM   VEHICULE ;
    SELECT '' AS 'AUTOMOBILE', * FROM   AUTOMOBILE ;

    Si par hasard vous utilisiez MySQL, la technique utilisée poserait un problème, car je crois savoir qu'il refuse les triggers associés aux vues...
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

Discussions similaires

  1. [MySQL] Comment gérer le Multilinguisme avec Mysql-PHP ?
    Par tavarlindar dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 10/12/2010, 13h49
  2. debutant avec MySQL Workbench
    Par Hydro999 dans le forum Outils
    Réponses: 0
    Dernier message: 22/08/2010, 19h04
  3. [Heritage] pb d'heritage avec MYSQL?
    Par thenightmare1985 dans le forum SQL Procédural
    Réponses: 3
    Dernier message: 20/11/2006, 23h58
  4. heritage avec MySql
    Par jamalmoundir dans le forum Requêtes
    Réponses: 4
    Dernier message: 10/05/2006, 14h32
  5. Heritage avec mysql
    Par picomz dans le forum SQL Procédural
    Réponses: 3
    Dernier message: 04/03/2006, 20h01

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