我正在尝试增加 MySQL 数据库架构的约束,为每个表添加外键约束。
表1: USERS
+---------+----------+-------------
| id | username | Other fields
+---------+----------+-------------
| 1 | John |
| 2 | Mark |
+---------+----------+-------------
id
INT(11)UNSIGNED NOT NULL AUTO_INCREMENTusername` VARCHAR(50)NOT NULL
PRIMARY KEY(
id
)
表2: DISKS (与 USERS 的一对多关系
+---------+----------+-----------+-------------
| 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
) INDEXfk_disks_idx
(id
ASC)约束
fk_disks
FOREIGN KEY(
id
)参考
database
。USERS
(id
)开启删除操作
ON UPDATE NO ACTION)
表3: FILES (与 DISKS 有一对多关系
) +---------+----------+----------+-----------+-------------
| 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 NULLPRIMARY KEY(
id
,id_disk
,id_user
) INDEXfk_files_idx
(id
ASC,id_user
ASC)约束
fk_files
外键(
id_disk
,id_user
,id_user
)参考
database
。DISKS
(id
)开启删除操作
ON UPDATE NO ACTION)
表2: FILES_ON_NAS (与 FILES 有一对一关系)
+-------+----------+----------+----------+-----------+-------------
| 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
) INDEXfk_files_on_nas_idx
(id
ASC)约束
fk_files_on_nas
外键(
id_files
,id_user
,id_disk
)参考
database
。FILES
(id
,id_user
,id_disk
)开启删除操作
ON UPDATE NO ACTION)
正如您所看到的那样,级联中的I引用表越多,我获得的主键就越多。如何设计数据库以避免复制主键,从而避免数据重复?我应该删除每个表的自动递增键吗?这是一个好习惯吗?
由于
答案 0 :(得分:3)
磁盘的ID足以唯一标识磁盘。因此没有理由将用户的ID包含在磁盘的主键中。这甚至是一个非常糟糕的主意,因为这意味着如果磁盘的用户发生变化,则需要修改主键。
同样的文件。文件ID唯一标识文件。因此没有理由将磁盘ID添加到文件的主键中。
答案 1 :(得分:1)
您可能希望阅读一些关于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)
);