web-dev-qa-db-fra.com

Modélisation d'une structure de base de données pour plusieurs types d'utilisateurs et leurs coordonnées

Je conçois une base de données qui stockera des utilisateurs de types différents. Ils seront principalement (mais pas exclusivement) des acteurs, réalisateurs et scénaristes. Actuellement, seuls quatre types d'utilisateurs sont pertinents. Il y a une chance extérieure que ce nombre augmente, mais la probabilité est faible - et dans ce cas, ce serait par un très petit nombre.

Le plan consiste à avoir une table users responsable à peu près uniquement de la connexion au site (colonnes name, email et password plus une ou deux autres telles comme s'ils ont été approuvés et mis à jour_à) et des tableaux supplémentaires pour chacun des types d'utilisateurs respectifs qui ont chacun leur propre ensemble unique de colonnes. Seuls les acteurs, par exemple, auront une colonne sur l'origine ethnique, seuls les réalisateurs auront une colonne bio et seuls les scénaristes devront fournir leur emplacement. Cependant, comme je n'ai jamais géré de base de données de cette complexité auparavant, je me demande comment organiser quelques aspects:

Premièrement, les utilisateurs peuvent être n'importe lequel, ou n'importe quelle combinaison, des types ci-dessus. Je comprends donc que j'aurais besoin de quelque chose comme (par exemple) un director_user table avec director_id et user_id Colonnes. Cela suffirait-il alors pour pouvoir filtrer tous les utilisateurs par type de rôle, etc.?

Deuxièmement, la plupart des utilisateurs auront l'option d'un profil Twitter et d'un numéro de téléphone. Et tous les acteurs devront inclure au moins une URL pour l'un de leurs autres profils d'acteurs en ligne; actuellement, ils peuvent en inclure trois, mais ce nombre peut augmenter. Ai-je raison de supposer qu'un tableau séparé pour chacun des profils/méthodes de contact possibles est un moyen optimal d'organiser les données?

10
verism

Selon mon interprétation de votre description du contexte commercial qui vous intéresse, vous avez affaire à un supertype-subtype1 structure où (a) Acteur, Réalisateur et Scénariste sont des sous-types d'entité de (b) Personne, leur supertype d'entité, et (c) lesdits sous-types sont pas s'excluent mutuellement.

De cette façon, si vous êtes intéressé par la construction d'une base de données relationnelle qui reflète un tel scénario avec précision — et par conséquent attendez-vous à ce qu'il fonctionne en tant que tel—, les clarifications suivantes concernant vos commentaires sont assez importantes en les points précédents, car ils ont des implications aux niveaux (1) conceptuel et (2) logique de représentation de la base de données en question:

  • […] Tableaux supplémentaires pour chacun des types d'utilisateurs respectifs qui ont chacun leur propre ensemble unique de colonnes.

  • […] Il n'y a que quatre types d'utilisateurs qui sont pertinents. Il y a une chance extérieure que ce nombre augmente, mais la probabilité est faible - et dans ce cas, ce serait par un très petit nombre.

Je développerai tous ces aspects et plusieurs autres facteurs critiques dans les sections ci-dessous.

Règles métier

Afin de définir d'abord le schéma conceptuel correspondant —qui peut être utilisé comme référence ultérieure afin que vous puissiez l'adapter pour vous assurer qu'il répond aux exigences d'information exact -, j'ai formulé quelques affaires règles particulièrement importantes:

  • A Personne peut effectuer un à deux ou trois (c'est-à-dire un à tous) Rôles2. En d'autres termes, une personne peut être
    • an Acteur et
    • a Directeur et
    • a Writer.
  • A Person peut se connecter via zéro ou un UserProfile.
  • Un acteur fournit un-deux-ou-trois URL3.
  • Un Acteur est groupé par un Ethnicité.
  • Un Ethnicité groupe zéro-un-ou-plusieurs Acteurs.
  • Un Writer est basé sur un Location.
  • A Emplacement est la base de zéro-un ou plus Écrivains.

Diagramme expositoire IDEF1X

Ensuite, j'ai créé l'IDEF1X4 diagramme montré dans Figure 1 , qui regroupe toutes les formulations ci-dessus ainsi que d'autres règles qui semblent pertinentes:

Figure 1 - IDEF1X Diagram for Person Roles and Contact Details in Cinema

Comme démontré, le Personne sur-type (i) a sa propre boîte, (ii) possède les propriétés ou les attributs qui s'appliquent aux tous les sous-types, et (iii ) présente des lignes qui le relient aux cases de chaque sous-type.

À son tour, chaque sous-type (a) apparaît dans sa propre boîte dédiée, et (b) détient exclusivement ses propriétés applicables. La PRIMARY KEY du supertype, PersonId, migre5 aux sous-types avec les noms de rôle6  ActorId, DirectorId et WriterId respectivement.

De plus, j'ai évité de coupler Person avec le type d'entité UserProfile, ce qui permet de séparer toutes leurs implications contextuelles, associations ou relations, etc. Le PersonId la propriété a migré vers UserProfile avec le nom de rôle UserId.

Vous déclarez dans le corps de la question que

Et tous les acteurs devront inclure au moins une URL pour l'un de leurs autres profils d'acteurs en ligne; actuellement, ils peuvent en inclure trois, mais ce nombre peut augmenter.

… So [~ # ~] url [~ # ~] est un type d'entité à part entière, et est directement associé au sous-type Acteur conformément avec cette citation.

Et, dans commentaires , vous spécifiez que

[…] Un acteur aura un headshot (photo), alors qu'un écrivain n'aura pas […]

… Puis, entre autres fonctionnalités, j'ai inclus Headshot comme propriété du type d'entité Actor.

Quant aux types d'entités Ethnicité et Emplacement, ils peuvent bien sûr impliquer des organisations plus complexes (par exemple, un Acteur peut appartenir à un, deux ou plusieurs groupes ethniques différents dans des proportions distinctes, et un écrivain peut être basé sur un lieu qui nécessite l'enregistrement du pays, de la région administrative, du comté, etc.) mais il ressemble à que les besoins de votre contexte commercial sont couverts avec succès avec les structures modélisées ici.

Naturellement, vous pouvez effectuer autant d'ajustements que nécessaire.

Conception logique illustrative SQL-DDL

Par conséquent, sur la base du diagramme IDEF1X montré et décrit ci-dessus, j'ai écrit la disposition DDL logique qui est montrée comme suit (j'ai fourni des notes sous forme de commentaires qui expliquent certaines des caractéristiques que j'estime particulièrement importantes en ce qui concerne les tableaux, les colonnes et les contraintes déclaré):

-- You should determine which are the most fitting 
-- data types and sizes for all your table columns 
-- depending on your business context characteristics.

-- Also, you should make accurate tests to define the 
-- most convenient INDEX strategies based on the exact 
-- data manipulation tendencies of your business needs.

-- As one would expect, you are free to utilize 
-- your preferred (or required) naming conventions. 

CREATE TABLE Person ( -- Represents the supertype.
    PersonId       INT      NOT NULL,
    FirstName      CHAR(30) NOT NULL,
    LastName       CHAR(30) NOT NULL,
    BirthDate      DATE     NOT NULL,
    GenderCode     CHAR(3)  NOT NULL,
    TwitterProfile CHAR(30) NOT NULL,
    PhoneNumber    CHAR(30) NOT NULL,
    EmailAddress   CHAR(30) NOT NULL,  
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT Person_PK  PRIMARY KEY (PersonId),
    CONSTRAINT Person_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
        FirstName,
        LastName,
        GenderCode,
        BirthDate
    ),
    CONSTRAINT Person_AK2 UNIQUE (TwitterProfile), -- ALTERNATE KEY.
    CONSTRAINT Person_AK3 UNIQUE (EmailAddress)    -- ALTERNATE KEY.
);

CREATE TABLE Ethnicity ( -- Its rows will serve a “look-up” purpose.
    EthnicityId     INT      NOT NULL,
    Name            CHAR(30) NOT NULL,  
    Description     CHAR(30) NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Ethnicity_PK PRIMARY KEY (EthnicityId),
    CONSTRAINT Ethnicity_AK UNIQUE      (Description)   
);

CREATE TABLE Actor ( -- Stands for one of the subtypes.
    ActorId         INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Headshot        CHAR(30) NOT NULL, -- May, e.g., contain a URL indicating the path where the photo file is actually stored. 
    EthnicityId     INT      NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Actor_PK            PRIMARY KEY (ActorId),
    CONSTRAINT ActorToPerson_PK    FOREIGN KEY (ActorId)
        REFERENCES Person (PersonId),
    CONSTRAINT ActorToEthnicity_PK FOREIGN KEY (EthnicityId)
        REFERENCES Ethnicity (EthnicityId)   
);

CREATE TABLE Director ( -- Denotes one of the subtypes
    DirectorId      INT       NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Bio             CHAR(120) NOT NULL,  
    Etcetera        CHAR(30)  NOT NULL,
    CreatedDateTime DATETIME  NOT NULL,
    -- 
    CONSTRAINT Director_PK         PRIMARY KEY (DirectorId),
    CONSTRAINT DirectorToPerson_PK FOREIGN KEY (DirectorId)
        REFERENCES Person (PersonId)   
);

CREATE TABLE Country (
    CountryCode     CHAR(2)  NOT NULL,
    Name            CHAR(30) NOT NULL,  
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Country_PK PRIMARY KEY (CountryCode),
    CONSTRAINT Country_AK UNIQUE      (Name)   
);

CREATE TABLE Location ( -- Its rows will serve a “look-up” purpose.
    CountryCode     CHAR(2)  NOT NULL,
    LocationCode    CHAR(3)  NOT NULL,
    Name            CHAR(30) NOT NULL,  
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Location_PK PRIMARY KEY (CountryCode, LocationCode),
    CONSTRAINT Location_AK UNIQUE      (CountryCode, Name)   
);

CREATE TABLE Writer ( -- Represents one of the subtypes.
    WriterId        INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    CountryCode     CHAR(2)  NOT NULL,
    LocationCode    CHAR(3)  NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Writer_PK           PRIMARY KEY (WriterId),
    CONSTRAINT WriterToPerson_PK   FOREIGN KEY (WriterId)
        REFERENCES Person (PersonId),
    CONSTRAINT WriterToLocation_PK FOREIGN KEY (CountryCode, LocationCode)
        REFERENCES Location (CountryCode, LocationCode)  
);

CREATE TABLE UserProfile (
    UserId          INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    UserName        CHAR(30) NOT NULL,
    Etcetera        CHAR(30) NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT UserProfile_PK PRIMARY KEY (UserId),
    CONSTRAINT UserProfile_AK UNIQUE      (UserName), -- ALTERNATE KEY.
    CONSTRAINT UserProfileToPerson_PK FOREIGN KEY (UserId)
        REFERENCES Person (PersonId)    
);

CREATE TABLE URL (
    ActorId       INT      NOT NULL,
    Address       CHAR(90) NOT NULL,
    Etcetera      CHAR(30) NOT NULL,
    AddedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT URL_PK        PRIMARY KEY (ActorId, Address), -- Composite PRIMARY KEY.
    CONSTRAINT URLtoActor_FK FOREIGN KEY (ActorId)
        REFERENCES Actor (ActorId)
);

Par conséquent, (1) chaque aspect singulier de la disposition logique ci-dessus porte une signification très précise de (2) une caractéristique singulière de l'environnement commercial d'intérêt7 —En accord avec l'esprit du cadre relationnel par Dr. Edgar Frank Codd -, parce que:

  • Chaque table de base représente un type d'entité individuel.
  • Chaque colonne représente une seule propriété du type d'entité respectif.
  • Un type de données spécifique est fixé pour chaque colonne afin de garantir que toutes les valeurs qu'il contient appartiennent à un particulier et un ensemble correctement délimité a, que ce soit INT, DATETIME, CHAR, etc. (et espérons que MySQL intégrera enfin le support DOMAIN dans une version proche).
  • Plusieurs contraintes sont configurés (de manière déclarative) afin de garantir que les assertions sous forme de lignes conservées dans toutes les tables respectent les règles métier déterminées au niveau conceptuel niveau.
  • Chaque ligne est destinée à transmettre une sémantique bien définie, par exemple, une ligne Person est lue

    La personne identifiée par PersonId r est appelée par le FirstName s et le LastName t, est née le BirthDate u, a le GenderCode v, tweets sur le TwitterProfile w, est atteint via PhoneNumber x, est contacté via l'adresse e-mail y, et a été enregistré sur CreatedDateTime z.

Avoir une disposition comme celle-ci est décidément favorable, car vous pouvez dériver de nouvelles tables (par exemple, des opérations SELECT qui rassemblent des colonnes FROM plusieurs tables à l'aide de la clause JOIN) qui - successivement - ont également une signification très précise (voir la section intitulé "Vues" ci-dessous).

Il convient de mentionner que, avec cette configuration, (i) une ligne représentant une instance de sous-type est identifiée par (ii) la même valeur PRIMARY KEY qui distingue la ligne indiquant l'occurrence de supertype complémentaire. Il est donc plus que opportun de noter que

  • (a) attacher une colonne extra pour contenir les substituts générés et attribués par le système8 pour (b) les tables représentant les sous-types est (c) entièrement superflu.

Avec cette conception logique, si de nouveaux sous-types sont définis comme pertinents dans votre contexte commercial, vous devrez déclarer une nouvelle table de base, mais cela se produit également lorsque d'autres types de types d'entités sont jugés importants, de sorte que ladite situation serait, dans fait, ordinaire.

Vues

Afin de "récupérer", par exemple, toutes les informations qui correspondent à un Acteur, Réalisateur ou Scénariste, vous peut déclarer certaines vues (c'est-à-dire dérivé ou exprimable tables) afin que vous puissiez sélectionner directement à partir d'une seule ressource sans avoir à écrire à chaque fois les JOIN concernés; Par exemple, avec la VUE déclarée ci-dessous, vous pouvez obtenir les informations "complètes" Acteur:

--
CREATE VIEW FullActor AS

    SELECT P.FirstName,
           P.Lastname,
           P.BirthDate,
           P.GenderCode,
           P.TwitterProfile,
           P.PhoneNumber,
           P.EmailAddress,
           A.Headshot,
           E.Name AS Ethnicity
         FROM Person P
         JOIN Actor A
           ON A.ActorId     = P.PersonId
         JOIN Ethnicity E
           ON E.EthnicityId = A.EthnicityId;
--

Bien sûr, vous pouvez suivre une approche similaire afin de récupérer les informations "complètes" Director et Writer:

--
CREATE VIEW FullDirector AS

    SELECT P.FirstName,
           P.Lastname,
           P.BirthDate,
           P.GenderCode,
           P.TwitterProfile,
           P.PhoneNumber,
           P.EmailAddress,
           D.Bio,
           D.Etcetera
         FROM Person P
         JOIN Director D
           ON D.DirectorId = P.PersonId; 

--
CREATE VIEW FullWriter AS

    SELECT P.FirstName,
           P.Lastname,
           P.BirthDate,
           P.GenderCode,
           P.TwitterProfile,
           P.PhoneNumber,
           P.EmailAddress,
           L.Name AS Location,
           C.Name AS Country
         FROM Person P
         JOIN Writer W
           ON W.WriterId     = P.PersonId
         JOIN Country C
           ON C.CountryCode  = W.CountryCode
         JOIN Location L
           ON L.LocationCode = W.LocationCode;   
--

J'ai posté toutes les instructions DDL et les vues DML ici discutées dans ce SQL Fiddle fonctionnant sur MySQL 5.6 afin que vous puissiez les voir et les tester "en action".


Notes de fin

1 Dans certaines techniques de modélisation conceptuelle, les associations de supertype-sous-type sont appelées relations superclass-subclass.

2 Bien que vous mentionniez qu'il existe en fait plus Rôles qu'une Personne peut effectuer, mais les trois que vous avez révélés sont assez bons pour discuter du scénario exposant plusieurs importants = ramifications.

3 Mais, comme vous l'avez noté, à l'avenir, un Acteur pourrait éventuellement fournir un à plusieurs URL.

4  Définition d'intégration pour la modélisation de l'information ( IDEF1X ) est une technique de modélisation hautement recommandable qui a été établie en tant que standard en décembre 1993 par le États-Unis National Institute of Standards and Technology (NIST). Il est basé sur (a) les premiers travaux théoriques rédigés par le seul auteur du modèle relationnel de données, c'est-à-dire le Dr E. F.Codd; sur (b) la vue entité-relation , développée par Dr P. P. Chen ; et également sur (c) la technique de conception de bases de données logiques, créée par Robert G. Brown.

5 La norme IDEF1X définit migration de clé comme "Le processus de modélisation consistant à placer la clé primaire d'une entité parent ou générique [c'est-à-dire un supertype] dans son entité enfant ou catégorie [c'est-à-dire un sous-type] comme une clé étrangère ".

6 Dans IDEF1X, un nom de rôle est une étiquette distinctive attribuée à un attribut FK afin d'exprimer la signification qu'il détient dans le cadre de son type d'entité respectif.

7 Sauf, naturellement, pour les propriétés conceptuelles hypothétiques (et les colonnes logiques) Director.Etcetera et UserProfile.Etcetera, qui ne sont que des espaces réservés que j'ai utilisés pour exposer le possibilité d'ajouter d'autres propriétés (et colonnes) qui s'appliquent au type d'entité conceptuel correspondant (et à la table logique).

8 Par exemple, en ajoutant une colonne supplémentaire avec l'attribut AUTO_INCREMENT à une table d'une base de données "en cours d'exécution" sur MySQL.

13
MDCCL

Vous devez diviser cela en plusieurs tableaux comme celui-ci (en affichant uniquement les colonnes nécessaires pour présenter le concept, pas nécessairement toutes les colonnes):

Users
ID   Username   FirstName   LastName   PasswordHash ...
 1   'Joe1'      'Joe'      'Smith'
 2   'Freddy'    'Fred'     'Jones'

Roles
ID   RoleType ....
 1   'Writer'
 2   'Director'
 3   'Actor'

User_Roles
User_ID   Role_ID ...
1         1
1         2
2         2
2         3

Cela vous donne une table pleine d'utilisateurs avec toutes les différentes colonnes d'utilisateurs, une table de rôles et une table de liaison pour connecter les deux ensemble.

Vous pouvez voir que Joe1 est à la fois scénariste et réalisateur par les entrées dans User_Roles. Et Freddy est à la fois réalisateur et acteur.

Cela vous permet également d'ajouter plus de rôles ultérieurement sans modifier le système. Insérez simplement des enregistrements pour le producteur ou l'éditeur ou quoi que ce soit sur la ligne.

Donc, pour trouver tous les noms d'utilisateur des acteurs, vous avez deux choix:

 Select Distinct Username
   from Users
  Where User_ID in (select User_ID from User_Roles where Role_ID = 3)

Ou si vous ne connaissez pas le numéro de role_ID, alors:

 Select Distinct Username
   from Users
  Where User_ID in (Select User_ID from User_Roles where Role_ID = 
                       (Select ID from Roles where RoleType = 'Actor')
                   )

Ou vous pouvez également le faire:

select u.Username, r.RoleType
  from Users u
 inner join User_Roles ur on ur.User_ID = u.ID
 inner join Roles r on r.ID = ur.Role_ID
 where r.RoleType = 'Actor'

(Dans cette version, vous pouvez également utiliser Where r.Role_ID = 3 pour obtenir les mêmes résultats.)

Mais j'utiliserais la 1ère requête et la clause WHERE que je connaissais. Dans un grand système, connaître le Role_ID s'exécute généralement plus rapidement que le texte, car les données numériques sont "plus faciles" et plus efficaces pour la plupart des moteurs SQL pour traiter les index.

Quant aux méthodes de contact ou aux photos ou autre, je les ferais de la même manière:

Attributes
ID    MethodText    ...
1     'TwitterID'
2     'URL'
3     'CellPhone'
4     'Email'
5     'PictureLink'

Role_Attributes
Role_ID  Attribute_ID isRequired
3        5             1
3        4             1
3        3             0

User_Attributes
User_ID  Attribute_ID  AttributeData
1         4            '[email protected]'
1         1            '@joe'
1         3            '555-555-5555'
1         5            'www.example.com/pics/myFace.png'

...etc. Ceux-ci seraient liés de la même manière que les utilisateurs aux rôles.

Cela montre que chaque rôle a de 0 à de nombreux attributs, qui peuvent être facultatifs. Ensuite, chaque utilisateur a 0 à plusieurs attributs, avec les données de ces attributs.

Cela vous permet d'ajouter de nouveaux attributs au fil du temps, sans réécrire de code; mettez simplement à jour les tables d'attributs et de role_attributes pour qu'elles correspondent à vos nouvelles règles. Il vous permet également de partager des attributs entre les rôles, sans ressaisir les mêmes données pour chaque utilisateur. Si deux rôles nécessitent des photos, ils n'ont qu'à télécharger 1 photo pour remplir cette exigence.

2
CaM