Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Datenbankstruktur/-design

Es gibt keine allgemeine Regel oder Best Practice, dass Fremdschlüssel nicht nullfähig sein sollten. Oft macht es für eine Entität durchaus Sinn, keine Beziehung zu einer anderen Entität zu haben. Beispielsweise haben Sie möglicherweise eine Tabelle mit Künstlern, die Sie verfolgen, aber im Moment haben Sie keine CDs von diesen Künstlern aufgenommen.

Was Medien (CD, DVD, BluRay) betrifft, die entweder Musik/Audio oder Software sein können, können Sie eine Tabelle mit den gemeinsamen Informationen und dann zwei Fremdschlüssel haben, einen für jede Erweiterungstabelle (AudioData und SoftwareData), aber einen muss NULL sein . Dies stellt eine Situation dar, die unter anderem als exklusiver Bogen bezeichnet wird. Das wird allgemein als ... problematisch angesehen.

Denken Sie an eine Oberklasse und zwei abgeleitete Klassen in einer OO-Sprache wie Java oder C++. Eine Möglichkeit, dies in einem relationalen Schema darzustellen, ist:

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 )
);

Wenn Sie nun nach einem Film suchen, durchsuchen Sie die AVData-Tabelle, verbinden sich dann mit der Media-Tabelle nach den restlichen Informationen und so weiter mit Software oder Spielen. Wenn Sie einen ID-Wert haben, aber nicht wissen, um welche Art es sich handelt, durchsuchen Sie die Medientabelle und der Typwert sagt Ihnen, mit welcher der drei (oder mehr) Datentabellen Sie sich verbinden müssen. Der Punkt ist, dass sich der FK auf auf bezieht die generische Tabelle, nicht daraus.

Natürlich kann ein Film, ein Spiel oder eine Software auf mehr als einem Medientyp veröffentlicht werden, sodass Sie Schnittmengentabellen zwischen den Media haben können Tabelle und den jeweiligen Datentabellen. Otoh, diese sind im Allgemeinen mit unterschiedlichen SKUs gekennzeichnet, sodass Sie sie möglicherweise auch als unterschiedliche Artikel behandeln möchten.

Der Code kann, wie zu erwarten, ziemlich kompliziert werden, wenn auch nicht allzu schlimm. Otoh, unser Designziel ist nicht Code-Einfachheit, sondern Datenintegrität. Dies macht es beispielsweise unmöglich, Spieldaten mit einem Filmelement zu mischen. Und Sie werden eine Reihe von Feldern los, von denen nur eines einen Wert haben muss und die anderen null sein müssen.