说使用"Composite keys as PRIMARY KEY is bad practice"
完全是胡说八道!
复合物PRIMARY KEY
通常是一件非常“好事”,并且是模拟日常生活中自然情况的唯一方法!
想一想经典的Databases-101学生和课程教学示例以及许多学生参加的许多课程!
创建表格课程和学生:
CREATE TABLE course
(
course_id SERIAL,
course_year SMALLINT NOT NULL,
course_name VARCHAR (100) NOT NULL,
CONSTRAINT course_pk PRIMARY KEY (course_id)
);
CREATE TABLE student
(
student_id SERIAL,
student_name VARCHAR (50),
CONSTRAINT student_pk PRIMARY KEY (student_id)
);
我将以PostgreSQL方言(和MySQL)为您提供示例-只需稍作调整即可在任何服务器上使用。
现在,您显然想要跟踪哪个学生正在学习哪门课程-因此您有了所谓的joining table
(也称为linking
,many-to-many
或m-to-n
表格)。它们associative entities
在更多技术术语中也被称为!
1门课程可以有很多学生。
1名学生可以参加许多课程。
因此,您创建一个联接表
CREATE TABLE course_student
(
cs_course_id INTEGER NOT NULL,
cs_student_id INTEGER NOT NULL,
-- now for FK constraints - have to ensure that the student
-- actually exists, ditto for the course.
CREATE CONSTRAINT cs_course_fk FOREIGN KEY (cs_course_id) REFERENCES course (course_id),
CREATE CONSTRAINT cs_student_fk FOREIGN KEY (cs_student_id) REFERENCES student (student_id)
);
现在,明智地给这张桌子加个表的唯一方法PRIMARY KEY
是将KEY
课程和学生结合起来。这样,您将无法获得:
学生和课程组合的副本
一门课程只能让同一名学生注册一次,并且
一个学生只能一次注册同一门课程
您还可以KEY
对每位学生的课程进行现成搜索- 又称覆盖率索引,
找不到没有学生的学生和没有上课的学生的课程很简单!
-db-fiddle 示例将PK约束折叠到了CREATE TABLE中。我更喜欢CREATE TABLE语句中包含所有内容。
ALTER TABLE course_student
ADD CONSTRAINT course_student_pk
PRIMARY KEY (cs_course_id, cs_student_id);
现在,如果您发现按课程搜索学生的速度很慢,可以使用UNIQUE INDEX
on(sc_student_id,sc_course_id)。
ALTER TABLE course_student
ADD CONSTRAINT course_student_sc_uq
UNIQUE (cs_student_id, cs_course_id);
有没有灵丹妙药添加索引-他们会作出INSERT
S和UPDATE
s ^慢,但在巨大的大有裨益下降SELECT
倍!它是由开发人员决定给他们的知识和经验指标,但要说复合PRIMARY KEY
s为总是不好是完全错误的。
对于联接表,通常只有 它们才有PRIMARY KEY
意义!连接表也经常是建模业务,自然或几乎我能想到的每个领域中发生的事情的唯一方法!
此PK也covering index
可用作帮助加快搜索速度的。在这种情况下,如果人们经常在(course_id,student_id)上进行搜索,那将是特别有用的,这是人们可能会想到的!
这只是一个小例子,说明组合PRIMARY KEY
可能是一个很好的主意,并且是模拟现实的唯一明智的方法!关闭我的头顶,我能想到的很多很多了。
我自己的作品中的一个例子!
考虑一个航班表,其中包含flight_id,出发和到达机场列表以及相关时间,然后还有一个机组人员的cab_crew表!
可以建模的唯一明智的方法是有一个flight_crew表,其中的flight_id和crew_id为attibutes,唯一明智的方法PRIMARY KEY
是使用两个字段的组合键!