首页 文章

使用生成的主键引用表

提问于
浏览
1

我试图增加我的 MySQL 数据库架构的约束,为每个表添加外键约束 .

表1: USERS

+---------+----------+-------------
    | id      | username | Other fields
    +---------+----------+-------------
    | 1       | John     |
    | 2       | Mark     |
    +---------+----------+-------------

id INT(11)UNSIGNED NOT NULL AUTO_INCREMENT username`VARCHAR(50)NOT NULL PRIMARY KEY(id)

表2: DISKS (与 USERS 的关系为 one to many

+---------+----------+-----------+-------------
    | id      | id_user  | disk_name | Other fields
    +---------+----------+-----------+-------------
    | 1       | 1        | disk A    |
    | 2       | 2        | disk B    |
    +---------+----------+-----------+-------------

id INT(11)UNSIGNED NOT NULL AUTO_INCREMENT id_user INT(11)NOT NULL,PRIMARY KEY(id,id_user)INDEX fk_disks_idx(id ASC)CONSTRAINT fk_disks FOREIGN KEY(id)REFERENCES database.USERS(id)ON DELETE NO ACTION ON更新无动作)

表3: FILES (与 DISKS 的关系为 one to many

+---------+----------+----------+-----------+-------------
    | id      | id_disk  | id_user  | file_name | Other fields
    +---------+----------+----------+-----------+-------------
    | 1       | 1        | 1        |           |
    | 2       | 2        | 2        |           |
    +---------+----------+----------+-----------+-------------

id INT(11)UNSIGNED NOT NULL AUTO_INCREMENT id_user INT(11)NOT NULL id_disk INT(11)NOT NULL PRIMARY KEY(id,id_disk,id_user)INDEX fk_files_idx(id ASC,id_user ASC)CONSTRAINT fk_files FOREIGN KEY(id_disk,id_user ,id_user)REFERENCES database.DISKS(id)ON DELETE NO ACTION ON UPDATE NO ACTION)

表2: FILES_ON_NAS (与 FILES 的关系为 one to one

+-------+----------+----------+----------+-----------+-------------
    | id    | id_files | id_user  | id_disk  | file_name | Other fields
    +-------+----------+----------+----------+-----------+-------------
    | 1     | 1        | 1        | 1        |           |
    | 2     | 1        | 2        | 2        |           |
    +-------+----------+----------+----------+-----------+-------------

id INT(11)UNSIGNED NOT NULL AUTO_INCREMENT id_files INT(11)NOT NULL,id_user INT(11)NOT NULL,id_disk INT(11)NOT NULL,PRIMARY KEY(id,id_files,id_user,id_disk)INDEX fk_files_on_nas_idx(id ASC )CONSTRAINT fk_files_on_nas FOREIGN KEY(id_files,id_user,id_disk)REFERENCES database.FILES(id,id_user,id_disk)ON DELETE NO ACTION ON UPDATE NO ACTION)

问题:

正如您所看到的那样,级联中的I引用表越多,我获得的主键就越多 . 如何设计数据库以避免复制主键,从而避免数据重复?我应该删除每个表的自动递增键吗?这是一个好习惯吗?

谢谢

3 回答

  • 1

    磁盘的ID足以唯一标识磁盘 . 因此没有理由将用户的ID包含在磁盘的主键中 . 这甚至是一个非常糟糕的主意,因为这意味着如果磁盘的用户发生变化,则需要修改主键 .

    对于文件也是如此 . 文件ID唯一标识文件 . 因此没有理由将磁盘ID添加到文件的主键中 .

  • 1

    我强烈建议不要删除自动增加的键 .

    但是,您不需要每次都创建一个新的主键:

    • 如果您希望多个用户共享一个磁盘,只需将 id_disk 的外键放在 USERS

    • 如果您希望一个用户可以拥有多个磁盘,则将 id_user 的外键改为 DISKS .

    当您面对多对多关系时,只使用这样的主键 . 在这种情况下,您需要创建一个新表来连接两个表;将两个表的主键作为外键,与您一样制作耦合主键 .

  • 3

    您可能想要阅读一些关于Database Normalization的内容 . 在您的情况下,我会使surrogate key id 成为表中唯一的主键 . 就像是:

    create table users (
        id integer not null auto_increment,
        username varchar(50),
        ...,
        primary key (id)
    );
    
    create table disks (
        id integer not null auto_increment,
        user_id integer,
        diskname varchar(50),
        ....,
        primary key (id),
        foreign key (user_id) references users (id)
    );
    

    对于 files ,您将不得不回答以下问题:文件所有权是直接依赖于文件,还是传递给磁盘所有权,还是所有权独立? John拥有的一个由Jack拥有的磁盘上的文件?对我来说似乎没问题,但您的域名可能有不同的规则 . 在这种情况下,从文件表中删除user_id(否则您的数据库将不在Third normal form中) .

    create table files (
        id integer not null auto_increment,
        disk_id integer,
        user_id integer, -- you have to decide whether this is necessary
        filename varchar(50),
        ....,
        primary key (id),
        foreign key (disk_id) references disks (id),
        foreign key (user_id) references users (id)
    );
    

相关问题