数据库 Structure/Design

Database Structure/Design

我想不出这个标题,所以我什至不知道从哪里开始为自己研究。 我必须建立一个数据库,其中我有一个 CD/DVDs 的 table,但是它们的娱乐类型需要 metadata/information 方面的不同属性,例如音乐 CD 有艺术家、出版商、制作人,光盘号等等。虽然一个软件可能有相似之处,但有一些是音乐所没有的,而且可能与电影和游戏相同。所以我不确定这在 E-R 图方面如何工作,到目前为止我决定:

CD/DVDs 在商品 table 或库存中 table 还不确定名称。

tbl_items -> item_id, item_format(DVD 或 CD,可能扩展到 blu-ray 或 hd-dvd), item_entertainment_type(音乐、电影等)<--- 也许在另一个不确定。 元数据 table 的外键,这样当元数据已经存在时为新的 CD/DVDs 进行交付时,我只需输入一个新项目,因此它是元数据和项目之间的一对多(项目>-- 元)。

我认为的问题是,具有可为空的外键字段并且只需选择要添加关系的外键字段是不好的做法,所以 musicMeta_id INT NULL, FOREIGN KEY musicMetaID REFERENCES tbl_musicMeta(musicMeta_id) 每种类型都这样吗?或者以某种方式合并它们,或者数据库有什么技巧。

我正在使用 MySQL 和 php。

谢谢!

我的意见:去掉 FOREIGN KEYs;请确保您有合适的 INDEXes.

没有外键不能为空的一般规则或最佳实践。很多时候,一个实体不与另一个实体建立关系是完全合理的。例如,您可能有 table 个您跟踪的艺术家,但目前您没有这些艺术家录制的 CD。

至于拥有可以是 music/audio 或软件的媒体(CD、DVD、BluRay),您可以拥有一个 table 和两个外键,一个到每个扩展 table(AudioData 和 SoftwareData),但其中一个必须是 NULL。这提出了一种情况,除其他外,称为排他弧。 通常被认为是...有问题的。

想想像 Java 或 C++ 这样的 OO 语言中的一个超类和两个派生 类。在关系模式中表示它的一种方法是:

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

现在,如果您正在寻找电影,您可以搜索 AVData table,然后加入媒体 table 以获取其余信息以及软件或游戏等。如果您有一个 ID 值但不知道它是什么类型,请搜索媒体 table,类型值会告诉您要加入三个(或更多)数据 table 中的哪一个。关键是 FK 指的是 通用 table,而不是它。

当然,一部电影或游戏或软件可以在多种媒体类型上发布,因此您可以在 Media table 和各自的媒体类型之间有交集 table数据 table 秒。 Otoh,这些通常标有不同的 SKU,因此您可能还想将它们视为不同的商品。

如您所料,代码可能会变得相当复杂,但还算不错。 Otoh,我们的设计目标不是代码简单,而是数据完整性。这使得无法混合,例如,游戏数据与电影项目。而且你摆脱了一组字段,其中只有一个必须有值而其他必须为空。