¡Decir que el uso de "Composite keys as PRIMARY KEY is bad practice"
es un completo disparate!
¡Los compuestos a PRIMARY KEY
menudo son algo muy "bueno" y la única forma de modelar situaciones naturales que ocurren en la vida cotidiana!
¡Piense en el clásico ejemplo de enseñanza Databases-101 de estudiantes y cursos y en los muchos cursos tomados por muchos estudiantes!
Crear mesas curso y alumno:
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)
);
Le daré el ejemplo en el dialecto PostgreSQL (y MySQL ): debería funcionar para cualquier servidor con un poco de ajuste.
Ahora, es obvio que desee realizar un seguimiento de las cuales estudiante está tomando el cual por supuesto - por lo que tiene lo que se llama joining table
(también llamados linking
, many-to-many
o m-to-n
tablas). ¡También se conocen como associative entities
en jerga más técnica!
1 curso puede tener muchos estudiantes.
1 estudiante puede tomar muchos cursos.
Entonces, creas una tabla de unión
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)
);
Ahora, la única manera sensata de darle una mesa a esta PRIMARY KEY
es hacer que sea KEY
una combinación de curso y estudiante. De esa manera, no puedes obtener:
un duplicado de combinación de estudiante y curso
un curso solo puede tener al mismo estudiante matriculado una vez, y
un estudiante solo puede matricularse en el mismo curso solo una vez
también tiene una búsqueda preparada KEY
en el curso por estudiante, también conocido como índice de cobertura ,
¡Es trivial encontrar cursos sin estudiantes y estudiantes que no toman cursos!
- El ejemplo db-fiddle tiene la restricción PK plegada en CREATE TABLE - Se puede hacer de cualquier manera. Prefiero tener todo en la declaración CREATE TABLE.
ALTER TABLE course_student
ADD CONSTRAINT course_student_pk
PRIMARY KEY (cs_course_id, cs_student_id);
Ahora, si descubriera que las búsquedas de estudiantes por curso fueron lentas, use un 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);
No hay ninguna bala de plata para añadir índices - que van a hacer que INSERT
s y UPDATE
es más lento, pero en la gran ventaja de la enorme disminución deSELECT
los tiempos! Depende del desarrollador decidir indexar dado su conocimiento y experiencia, pero decir que los compuestos siemprePRIMARY KEY
son malos es simplemente incorrecto.
¡En el caso de unir tablas, generalmente son las únicas PRIMARY KEY
que tienen sentido! ¡Las tablas de unión también son muy frecuentemente la única forma de modelar lo que sucede en los negocios o la naturaleza o en prácticamente todos los ámbitos que se me ocurren!
Esta PK también es útil como una covering index
que puede ayudar a acelerar las búsquedas. En este caso, sería particularmente útil si uno estuviera buscando regularmente en (course_id, student_id), lo cual, uno podría imaginar, ¡a menudo puede ser el caso!
Este es solo un pequeño ejemplo de dónde un compuesto PRIMARY KEY
puede ser una muy buena idea, ¡y la única forma sensata de modelar la realidad! Fuera de mi cabeza, puedo pensar en muchos, muchos más.
Un ejemplo de mi propio trabajo!
¡Considere una tabla de vuelo que contiene un flight_id, una lista de aeropuertos de salida y llegada y los horarios relevantes y luego también una tabla de cabina con tripulantes!
La única forma sensata de modelar esto es tener una tabla flight_crew con el flight_id y el crew_id como atributos, ¡y la única forma sensata PRIMARY KEY
es utilizar la clave compuesta de los dos campos!