Сказать, что использование "Composite keys as PRIMARY KEY is bad practice"
это полная ерунда!
Композиты PRIMARY KEY
часто являются очень «хорошей вещью» и единственным способом моделирования естественных ситуаций, возникающих в повседневной жизни!
Подумайте о классическом учебном примере Базы данных-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
по курсу для каждого студента - AKA индекс покрытия ,
тривиально найти курсы без студентов и студентов, которые не посещают курсы!
- В примере 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
с и UPDATE
S медленнее, но на большой выгоду чрезвычайно убывающиеSELECT
раз! Разработчик должен решить индексировать, учитывая их знания и опыт, но говорить, что составные PRIMARY KEY
s всегда плохи, просто неправильно.
В случае объединения таблиц они обычно являются единственными, PRIMARY KEY
которые имеют смысл! Присоединение к столам также очень часто является единственным способом моделирования того, что происходит в бизнесе или на природе, или практически во всех сферах, которые я могу придумать!
Этот ПК также используется в качестве covering index
ускорения поиска. В этом случае было бы особенно полезно, если бы кто-то регулярно проводил поиск (course_id, student_id), что, как можно себе представить, часто имело бы место!
Это всего лишь небольшой пример того, как композит PRIMARY KEY
может быть очень хорошей идеей и единственным разумным способом моделирования реальности! Сверху головы я могу думать о многом другом.
Пример из моей собственной работы!
Рассмотрим таблицу полетов, содержащую flight_id, список аэропортов вылета и прилета и соответствующее время, а также таблицу cab_crew с членами экипажа!
Только разумный способ это может быть смоделировано, чтобы иметь таблицу flight_crew с flight_id и crew_id как и атрибуты объявления единственными разумным PRIMARY KEY
, чтобы использовать составной ключ из двух полей!