web-dev-qa-db-fra.com

Conception d'une base de données pour un domaine professionnel de jeux vidéo avec plusieurs relations plusieurs-à-plusieurs

Je suis relativement nouveau dans la conception de bases de données et j'ai décidé de créer ma propre base de données hypothétique pour la pratique. Cependant, j'ai du mal à le modéliser et à le normaliser, car j'estime qu'il existe de nombreuses relations plusieurs-à-plusieurs (M: N).

Description générale du scénario

La base de données est destinée à conserver des données sur divers People qui ont travaillé sur la série Zelda. Je veux garder une trace de la console (s) sur laquelle un je peut être joué, employés qui ont joué un rôle dans la - Jeux développement, le Jobs le Employé avait (beaucoup Employés travaillé sur différents Jobs sur plusieurs Jeux), etc.

Règles métier

  • Multiple Employés peut fonctionner sur plusieurs Jeux.
  • Plusieurs Jeux peuvent être sur le même Console.
  • Multiple Consoles peut être une plate-forme pour le même Game.
  • Plusieurs Employés peuvent avoir le même Travail.
  • Un Employé peut avoir plusieurs Jobs.
  • Un je peut avoir plusieurs employés.
  • Un Je peut avoir plusieurs types de Jobs dans son développement
  • Plusieurs Jeux peuvent avoir le même type de Travail attaché.
  • Un Console peut avoir plusieurs People travaillant dessus.
  • Une personne peut fonctionner sur plusieurs consoles.

Noms d'attributs et exemples de valeurs

  • Nom de l'employé, qui peut être divisé en Premier et Dernier (par exemple "John" et "Doe")
  • Titre du je (par exemple "Ocarina of Time")
  • Titre du poste (par exemple "Level Design", "Director", "Composure", "Level Designer", "Programmer", "Localization", etc.).
  • Nom de la console (par exemple "Game Boy Advance")

Le problème

Jusqu'à présent, peu importe ce que je conçois, il existe des redondances de données et des relations M: N entre les types d'entités d'intérêt partout. Cependant, je pense que les concepteurs de bases de données doivent constamment rencontrer ce type de problème, il doit donc y avoir une solution.


Note: Je suis bien capable de trouver les données pour remplir la table, le problème est de l'organiser dans une base de données avec des tables sous une forme normalisée.

16
dpolaristar

Oui, l'identification d'associations ou de relations plusieurs-à-plusieurs (M: N pour plus de brièveté) est une situation à laquelle un praticien de base de données est confronté assez souvent lorsqu'il établit un schéma conceptuel. Les associations desdits ratios de cardinalité se produisent dans des environnements commerciaux de nature très différente, et lorsqu'elles sont correctement représentées au niveau logique au moyen, par exemple, d'un arrangement SQL-DDL, elles le font pas introduire des redondances nuisibles.

De cette façon, l'objectif d'un exercice de modélisation de base de données devrait être de refléter les caractéristiques pertinentes du contexte commercial d'intérêt avec haute précision ; par conséquent, si vous identifiez correctement qu'il existe de nombreuses associations M: N, alors vous devez les exprimer dans (a) le schéma conceptuel et également dans (b) les déclarations de niveau logique respectives, quel que soit le nombre de connexions de ce type de ratio de cardinalité - ou de tout autre - à traiter.

Règles métier

Vous avez fourni une question bien contextualisée et avez également précisé que la base de données sur laquelle vous travaillez est purement hypothétique, ce qui est un point important car j'estime qu'un scénario commercial "réel" comme celui à l'étude serait beaucoup plus étendu. et, par conséquent, impliquerait des exigences d'information plus complexes.

J'ai décidé (1) d'apporter quelques modifications et extensions aux règles commerciales que vous avez fournies afin (2) de produire un schéma conceptuel plus descriptif - bien que toujours assez hypothétique -. Voici quelques-unes des formulations que j'ai rassemblées:

  • A Party1 est soit une personne , soit une organisation
  • A Party is classified by exactly-one PartyType
  • A PartyType classifies zero-one-or-many Parties
  • Une organisation développe des produits à un ou plusieurs
  • A Product is either a System or a Game
  • A Product is classified by exactly-one ProductType
  • A System is catalogued by exactly-one SystemType
  • A Game can be played via one-to-many Systems
  • A System is used to play one-to-many Games
  • A Game is classified by zero-one-or-many Genres
  • A Genre classifies zero-one-or-many Games
  • A Product originates one-to-many Jobs
  • A Job is fulfilled by zero-one-or-many People, who are playing the Role of Collaborators
  • A Person is a Collaborator in zero-one-or-many Jobs

1  Parti est un terme utilisé dans des contextes juridiques pour désigner un individu ou un groupe d'individus qui composent une seule entité, donc cette dénomination convient pour représenter les gens et Organisations .


Diagramme IDEF1X

Par la suite, j'ai créé l'IDEF1X2 diagramme montré dans Figure 1 (assurez-vous de cliquer sur le lien pour le voir dans une résolution plus élevée), consolidant dans un seul appareil graphique les règles commerciales présentées ci-dessus (ainsi que d'autres qui semblent pertinentes):

Figure 1 - Video Gae Jobs IDEF1X diagram


2  Définition d'intégration pour la modélisation de l'information ( IDEF1X ) est une technique de modélisation de données hautement recommandable qui a été établie en tant que norme en décembre 1993 par les États-Unis National Institute of Standards and Technology (NIST). Il est basé sur (a) les premiers éléments théoriques rédigés par le seul auteur du modèle relationnel, c'est-à-dire le Dr E. F.Codd; sur (b) la vue entité-relation des données, 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.


Comme vous pouvez le voir, je n'ai représenté que trois associations M: N au moyen des types d'entité associative correspondants , à savoir:

  • Collaborateur
  • SystemGame
  • GameGenre

Entre autres aspects, il existe deux structures distinctes supertype-sous-type , où:

  • Personne et Organisation sont des sous-types d'entités mutuellement exclusifs de Parti , leur super-type d'entité

  • Le produit est le sur-type du système et du jeu , qui sont à leur tour des sous-types mutuellement exclusifs

Dans le cas où vous n'êtes pas familier avec les associations supertype-sous-type, vous pourriez trouver de l'aide, par exemple, mes réponses aux questions intitulées:

Exemple de disposition logique SQL-DDL

Successivement, nous devons nous assurer qu'au niveau logique:

  • Chaque type d'entité est représenté par une table de base individuelle
  • Chaque propriété unique du type d'entité applicable est indiquée par une colonne particulière
  • Un type de données exact est fixé pour chaque colonne afin de garantir que toutes les valeurs qu'il contient appartiennent à un ensemble particulier et bien défini, que ce soit INT, DATETIME, CHAR, etc. (bien sûr, lorsque vous utilisez, par exemple, Firebird ou PostgreSQL , vous pouvez utiliser les DOMAINs les plus puissants)
  • Plusieurs contraintes sont configurées (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 à le niveau conceptuel

J'ai donc déclaré l'arrangement DDL suivant basé sur le diagramme IDEF1X montré précédemment:

CREATE TABLE PartyType ( -- Stands for an independent entity type.
    PartyTypeCode CHAR(1)  NOT NULL, -- To retain 'P' or 'O'.
    Name          CHAR(30) NOT NULL, -- To keep 'Person' or 'Organization'.
    --  
    CONSTRAINT PartyType_PK PRIMARY KEY (PartyTypeCode)
);

CREATE TABLE Party ( -- Represents an entity supertype.
    PartyId         INT       NOT NULL,
    PartyTypeCode   CHAR(1)   NOT NULL, -- To hold the value that indicates the type of the row denoting the complementary subtype occurrence: either 'P' for 'Person' or 'O' for 'Organization'.
    CreatedDateTime TIMESTAMP NOT NULL,  
    --
    CONSTRAINT Party_PK            PRIMARY KEY (PartyId),
    CONSTRAINT PartyToPartyType_FK FOREIGN KEY (PartyTypeCode)
        REFERENCES PartyType (PartyTypeCode)
);

CREATE TABLE Person ( -- Denotes an entity subtype.
    PersonId        INT      NOT NULL, -- To be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    FirstName       CHAR(30) NOT NULL,
    LastName        CHAR(30) NOT NULL,
    GenderCode      CHAR(3)  NOT NULL,
    BirthDate       DATE     NOT NULL,
    --
    CONSTRAINT Person_PK PRIMARY KEY        (PersonId),
    CONSTRAINT Person_AK UNIQUE             (FirstName, LastName, GenderCode, BirthDate), -- Composite ALTERNATE KEY.
    CONSTRAINT PersonToParty_FK FOREIGN KEY (PersonId)
        REFERENCES Party (PartyId)
);

CREATE TABLE Organization ( -- Stands for an entity subtype.
    OrganizationId  INT      NOT NULL, -- To be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Name            CHAR(30) NOT NULL,
    FoundingDate    DATE     NOT NULL,
    --
    CONSTRAINT Organization_PK        PRIMARY KEY (OrganizationId),
    CONSTRAINT Organization_AK        UNIQUE      (Name), -- Single-column ALTERNATE KEY.
    CONSTRAINT OrganizationToParty_FK FOREIGN KEY (OrganizationId)
        REFERENCES Party (PartyId)
);

CREATE TABLE ProductType ( -- Represents an independent entity type.
    ProductTypeCode CHAR(1)  NOT NULL, -- To enclose the values 'S' and 'G' in the corresponding rows.
    Name            CHAR(30) NOT NULL, -- To comprise the values 'System' and 'Person' in the respective rows.
    --
    CONSTRAINT ProductType_PK PRIMARY KEY (ProductTypeCode)
);

CREATE TABLE Product ( -- Denotes an entity supertype.
    OrganizationId  INT      NOT NULL,
    ProductNumber   INT      NOT NULL,
    ProductTypeCode CHAR(1)  NOT NULL, -- To keep the value that indicates the type of the row denoting the complementary subtype occurrence: either 'S' for 'System' or 'G' for 'Game'.
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT Product_PK               PRIMARY KEY (OrganizationId, ProductNumber), -- Composite PRIMARY KEY.
    CONSTRAINT ProductToOrganization_FK FOREIGN KEY (OrganizationId)
        REFERENCES Organization (OrganizationId),
    CONSTRAINT ProductToProductType_FK  FOREIGN KEY (ProductTypeCode)
        REFERENCES ProductType (ProductTypeCode)
);

CREATE TABLE SystemType ( -- Stands for an independent entity type.
    SystemTypeCode CHAR(1)  NOT NULL,
    Name           CHAR(30) NOT NULL,
     --
    CONSTRAINT SystemType_PK PRIMARY KEY (SystemTypeCode)
);

CREATE TABLE MySystem ( -- Represents a dependent entity type.
    OrganizationId   INT      NOT NULL, -- To be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    SystemNumber     INT      NOT NULL,
    SystemTypeCode   CHAR(1)  NOT NULL,
    ParticularColumn CHAR(30) NOT NULL,
    --
    CONSTRAINT System_PK              PRIMARY KEY (OrganizationId, SystemNumber),
    CONSTRAINT SystemToProduct_FK     FOREIGN KEY (OrganizationId, SystemNumber)
        REFERENCES Product (OrganizationId, ProductNumber),
    CONSTRAINT SystemToSystemType_FK  FOREIGN KEY (SystemTypeCode)
        REFERENCES SystemType (SystemTypeCode)
);

CREATE TABLE Game ( -- Denotes an entity subtype.
    OrganizationId INT      NOT NULL, -- To be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    GameNumber     INT      NOT NULL,
    SpecificColumn CHAR(30) NOT NULL,
    --
    CONSTRAINT Game_PK          PRIMARY KEY (OrganizationId, GameNumber),
    CONSTRAINT GameToProduct_FK FOREIGN KEY (OrganizationId, GameNumber)
         REFERENCES Product (OrganizationId, ProductNumber)
);

CREATE TABLE Genre ( -- Stands for an independent entity type.
    GenreNumber INT      NOT NULL,
    Name        CHAR(30) NOT NULL,  
    Description CHAR(90) NOT NULL,
    --
    CONSTRAINT Genre_PK  PRIMARY KEY (GenreNumber),
    CONSTRAINT Genre_AK1 UNIQUE      (Name),
    CONSTRAINT Genre_AK2 UNIQUE      (Description)
);

CREATE TABLE SystemGame ( -- Represents an associative entity type or M:N association.
    SystemOrganizationId INT      NOT NULL,  
    SystemNumber         INT      NOT NULL,  
    GameOrganizationId   INT      NOT NULL,    
    GameNumber           INT      NOT NULL,
    CreatedDateTime      DATETIME NOT NULL,
    -- 
    CONSTRAINT SystemGame_PK         PRIMARY KEY (SystemOrganizationId, SystemNumber, GameOrganizationId, GameNumber), -- Composite PRIMARY KEY.
    CONSTRAINT SystemGameToSystem_FK FOREIGN KEY (SystemOrganizationId, SystemNumber) -- Multi-column FOREIGN KEY.
        REFERENCES MySystem (OrganizationId, SystemNumber),
    CONSTRAINT SystemGameToGame_FK   FOREIGN KEY (SystemOrganizationId, GameNumber) -- Multi-column FOREIGN KEY.
        REFERENCES Game (OrganizationId, GameNumber)  
);

CREATE TABLE GameGenre ( -- Denotes an associative entity type or M:N association.
    GameOrganizationId INT      NOT NULL,    
    GameNumber         INT      NOT NULL,
    GenreNumber        INT      NOT NULL,  
    CreatedDateTime    DATETIME NOT NULL,
    -- 
    CONSTRAINT GameGenre_PK        PRIMARY KEY (GameOrganizationId, GameNumber, GenreNumber), -- Composite PRIMARY KEY.
    CONSTRAINT GameGenreToGame_FK  FOREIGN KEY (GameOrganizationId, GameNumber)
        REFERENCES Game (OrganizationId, GameNumber), -- Multi-column FOREIGN KEY.
    CONSTRAINT GameGenreToGenre_FK FOREIGN KEY (GenreNumber)
        REFERENCES Genre (GenreNumber) 
);

CREATE TABLE Job ( -- Stands for an associative entity type or M:N association.
    OrganizationId  INT      NOT NULL,
    ProductNumber   INT      NOT NULL,
    JobNumber       INT      NOT NULL,
    Title           CHAR(30) NOT NULL,  
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT Job_PK          PRIMARY KEY (OrganizationId, ProductNumber, JobNumber), -- Composite PRIMARY KEY.
    CONSTRAINT Job_AK          UNIQUE      (Title), -- Single-column ALTERNATE KEY.
    CONSTRAINT JobToProduct_FK FOREIGN KEY (OrganizationId, ProductNumber) -- Multi-column FOREIGN KEY.
        REFERENCES Product (OrganizationId, ProductNumber)
);

CREATE TABLE Collaborator ( -- Represents an associative entity type or M:N association.
    CollaboratorId   INT      NOT NULL,    
    OrganizationId   INT      NOT NULL,
    ProductNumber    INT      NOT NULL,
    JobNumber        INT      NOT NULL,
    AssignedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT Collaborator_PK         PRIMARY KEY (CollaboratorId, OrganizationId, ProductNumber, JobNumber), -- Composite PRIMARY KEY.
    CONSTRAINT CollaboratorToPerson_FK FOREIGN KEY (CollaboratorId)
    REFERENCES Person (PersonId),  
    CONSTRAINT CollaboratorToJob_FK    FOREIGN KEY (OrganizationId, ProductNumber, JobNumber) -- Multi-column FOREIGN KEY.
       REFERENCES Job (OrganizationId, ProductNumber, JobNumber)
);

Il est opportun de souligner qu'il existe des déclarations de contraintes composites PRIMARY KEY sur plusieurs tables, qui représentent la hiérarchie des connexions qui ont lieu entre les types d'entités conceptuelles, arrangement qui peut être très bénéfique avec en ce qui concerne la récupération de données lorsque, par exemple, l'expression d'opérations SELECT qui incluent des clauses JOIN pour obtenir des tables dérivées .

Oui, (i) chaque association M: N et (ii) chacun des types d'entités associés sont désignés par (iii) le tableau correspondant dans la structure DDL logique, alors faites particulièrement attention aux contraintes PRIMARY et FOREIGN KEY (et aux notes que j'ai laissées en tant que commentaires) de tableaux représentant ces éléments conceptuels, car ils aident à garantir que les connexions entre les lignes pertinentes respectent les ratios de cardinalité applicables.

L'utilisation des clés composites a été introduite par Dr. EF Codd de l'origine même du paradigme relationnel, comme démontré dans les exemples qu'il a inclus dans son article fondateur de 1970 intitulé Un modèle relationnel pour les grandes banques de données partagées (qui, précisément, présente également la méthode la plus élégante pour gérer les associations conceptuelles M: N).

J'ai installé n db <> fiddle et n SQL Fiddle , tous deux fonctionnant sur Microsoft SQL Server 2014, afin que la structure puisse être testée "en action".

Normalisation

La normalisation est une procédure de niveau logique qui implique, fondamentalement parlant:

  1. Éliminer les colonnes non atomiques via la première forme normale afin que la manipulation et la restriction des données soient beaucoup plus faciles à gérer par le sous-langage de données utilisé (par exemple, SQL).

  2. Se débarrasser des dépendances indésirables entre les colonnes d'une table spécifique grâce aux formes normales successives pour éviter les anomalies de mise à jour .

Naturellement, il faut tenir compte de la signification véhiculée par les tables et colonnes en cause.

J'aime considérer la normalisation comme un test fondé sur la science qu'un concepteur applique aux éléments pertinents une fois qu'il a défini un arrangement de niveau logique stable afin de déterminer si ses éléments sont conformes avec chacune des formes normales ou non. Ensuite, si nécessaire, le concepteur prend les mesures correctives appropriées.

Redondance

Dans le modèle relationnel, alors que la duplication des valeurs contenues dans les colonnes est non seulement acceptable mais attendue , les lignes en double sont interdites . Dans cette mesure, pour autant que je puisse voir, les doublons de lignes et autres types de redondances nuisibles sont évités dans tous les tableaux compris dans la disposition logique exposée précédemment, vous voudrez peut-être clarifier votre préoccupation à cet égard.

Quoi qu'il en soit, vous pouvez certainement (a) évaluer par vous-même ladite structure à l'aide des formes normales pour définir si elle répond aux exigences et (b) la modifier si nécessaire.

Ressources associées

  • Dans cette série d'articles je présente quelques réflexions sur une association M: N simple qui peut interrelier les instances de deux types d'entités différents .
  • Dans cet autre je propose une approche pour gérer une occurrence de la construction "Bill of Materials" ou "Parts Explosion", dans laquelle je décris comment connecter distinct instances du même type d'entité .

Associations ternaires

Il y a un autre aspect important que vous avez évoqué via les commentaires (publié dans une réponse maintenant supprimée):

Chaque fois que j'essaie de faire un pont, les éléments de ce pont ont également un plusieurs à plusieurs, j'ai l'impression que ce n'est pas autorisé ou du moins découragé.

Cette circonstance semble indiquer que l'une de vos préoccupations concerne les associations ternaires conceptuelles . Fondamentalement, ce type d'association se produit lorsqu'il existe (1) une relation impliquant (2) deux autres relations, en d'autres termes "une relation entre des relations" - une situation typique aussi, car une relation est une entité à part entière -.

Ces dispositions, lorsqu'elles sont correctement gérées, n'entraînent pas non plus de licenciements préjudiciables. Et, oui, s'il y a un certain cas d'utilisation où vous identifiez que de telles relations se présentent parmi les types d'entités "du monde réel", vous devez (i) modéliser et (ii) les déclarer avec précision au niveau logique.

  • Voici une question et réponse où nous analysons un domaine de discours sur les enquêtes , qui comprend un exemple d'association ternaire.
  • Dans cette très bonne réponse , @ Ypercube présente un diagramme et la structure DDL respective pour une relation en forme de diamant intéressante , qui est très similaire à cette classe de scénarios.
18
MDCCL