Mysql
 sql >> Base de données >  >> RDS >> Mysql

Structure/conception de la base de données

Il n'y a pas de règle générale ou de meilleure pratique, les clés étrangères ne doivent pas être nulles. Souvent, il est parfaitement logique qu'une entité n'ait pas de relation avec une autre entité. Par exemple, vous pouvez avoir un tableau d'artistes que vous suivez mais, pour le moment, vous n'avez aucun CD enregistré par ces artistes.

En ce qui concerne les médias (CD, DVD, BluRay) qui peuvent être de la musique/audio ou des logiciels, vous pouvez avoir une table avec les informations en commun, puis deux clés étrangères, une pour chaque table d'extension (AudioData et SoftwareData), mais une doit être NULL . Cela présente une situation appelée, entre autres, un arc exclusif. Ceci est généralement considéré comme... problématique.

Pensez à une superclasse et à deux classes dérivées dans un langage OO comme Java ou C++. Une façon de représenter cela dans un schéma relationnel est :

create table Media(
    ID      int not null, -- identity, auto_generated, generated always as identity...
    Type    char( 1 ) not null,
    Format  char( 1 ) not null,
    ... <other common data>,
    constraint PK_Media primary key( ID ),
    constraint FK_Media_Type foreign key( Type )
        references MediaTypes( ID ), -- A-A/V, S-Software, G-Game
    constraint FK_Media_Format foreign key( Format )
        references MediaFormats( ID ) -- C-CD, D-DVD, B-BluRay, etc.
);
create unique index UQ_Media_ID_Type( ID, Type ) on Media;
create table AVData( -- For music and video
    ID       int not null,
    Type     char( 1 ) not null,
    ... <audio-only data>,
    constraint PK_AVData primary key( ID ),
    constraint CK_AVData_Type check( Type = 'A',
    constraint FK_AVData_Media foreign key( ID, Type )
        references Media( ID, Type )
);
create table SWData( -- For software, data
    ID       int not null,
    Type     char( 1 ) not null,
    ... <software-only data>,
    constraint PK_SWData primary key( ID ),
    constraint CK_SWData_Type check( Type = 'S',
    constraint FK_SWData_Media foreign key( ID, Type )
        references Media( ID, Type )
);
create table GameData( -- For games
    ID       int not null,
    Type     char( 1 ) not null,
    ... <game-only data>,
    constraint PK_GameData primary key( ID ),
    constraint CK_GameData_Type check( Type = 'G',
    constraint FK_GameData_Media foreign key( ID, Type )
        references Media( ID, Type )
);

Maintenant, si vous recherchez un film, vous recherchez la table AVData, puis rejoignez la table Media pour le reste des informations et ainsi de suite avec des logiciels ou des jeux. Si vous avez une valeur ID mais que vous ne savez pas de quel type il s'agit, recherchez la table Media et la valeur Type vous indiquera laquelle des trois tables de données (ou plus) joindre. Le fait est que le FK fait référence à à la table générique, pas à partir de celle-ci.

Bien sûr, un film ou un jeu ou un logiciel peut être publié sur plusieurs types de médias, vous pouvez donc avoir des tables d'intersection entre les Media table et les tables de données respectives. Otoh, ceux-ci sont généralement étiquetés avec différents SKU, vous pouvez donc également les traiter comme des articles différents.

Le code, comme vous vous en doutez, peut devenir assez compliqué, mais pas trop mal. Otoh, notre objectif de conception n'est pas la simplicité du code mais l'intégrité des données. Cela rend impossible le mélange, par exemple, de données de jeu avec un élément de film. Et vous vous débarrassez d'un ensemble de champs où un seul doit avoir une valeur et les autres doivent être nuls.