Dizer que o uso de "Composite keys as PRIMARY KEY is bad practice"
é um total absurdo!
Os compostos PRIMARY KEY
são frequentemente uma "coisa boa" e a única maneira de modelar situações naturais que ocorrem na vida cotidiana!
Pense no exemplo clássico de ensino de bancos de dados-101 de estudantes e cursos e nos muitos cursos realizados por muitos estudantes!
Crie tabelas de curso e aluno:
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)
);
Vou dar o exemplo no dialeto do PostgreSQL (e MySQL ) - deve funcionar para qualquer servidor com alguns ajustes.
Agora, você obviamente quer manter o controle de quais estudante está tomando qual curso - então você tem o que é chamado um joining table
(também chamados linking
, many-to-many
ou m-to-n
tabelas). Eles também são conhecidos como associative entities
no jargão mais técnico!
Um curso pode ter muitos alunos.
1 aluno pode fazer muitos cursos.
Então, você cria uma tabela de junção
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)
);
Agora, a única maneira de dar uma sensata a esta tabela PRIMARY KEY
é fazer disso KEY
uma combinação de curso e aluno. Dessa forma, você não pode obter:
uma duplicata da combinação de alunos e cursos
você também tem uma pesquisa pronta KEY
no curso por aluno - também conhecido como índice de cobertura ,
é trivial encontrar cursos sem alunos e estudantes que não estão fazendo nenhum curso!
- O exemplo db-fiddle possui a restrição PK dobrada na CREATE TABLE - Isso pode ser feito de qualquer maneira. Prefiro ter tudo na instrução CREATE TABLE.
ALTER TABLE course_student
ADD CONSTRAINT course_student_pk
PRIMARY KEY (cs_course_id, cs_student_id);
Agora, você poderia, se estivesse achando que as pesquisas por aluno por curso eram lentas, use 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);
Não é nenhuma bala de prata para a adição de índices - que vai fazer INSERT
s e UPDATE
mais lento, mas o grande benefício da enorme decrescentesSELECT
vezes! Cabe ao desenvolvedor decidir indexar, considerando seu conhecimento e experiência, mas dizer que PRIMARY KEY
s compostos são sempre ruins é simplesmente errado.
No caso de unir tabelas, elas geralmente são as únicas PRIMARY KEY
que fazem sentido! As tabelas de junção também são frequentemente a única maneira de modelar o que acontece nos negócios ou na natureza ou em praticamente todas as esferas em que consigo pensar!
Esse PK também é útil, pois covering index
pode ajudar a acelerar as pesquisas. Nesse caso, seria particularmente útil se alguém estivesse pesquisando regularmente (id do curso, id do aluno) o que, imaginamos, pode ser o caso!
Este é apenas um pequeno exemplo de onde um composto PRIMARY KEY
pode ser uma boa idéia e a única maneira sensata de modelar a realidade! Do alto da minha cabeça, consigo pensar em muitos mais.
Um exemplo do meu próprio trabalho!
Considere uma tabela de voo contendo um flight_id, uma lista de aeroportos de partida e chegada e os horários relevantes e, em seguida, também uma tabela de tripulação de cabine com tripulantes!
A única maneira sensata de modelar isso é ter uma tabela de flight_crew com o flight_id e o crew_id como atributos, e o único são PRIMARY KEY
é usar a chave composta dos dois campos!