ALTER TABLE para agregar una clave primaria compuesta

195

Tengo una mesa llamada provider. Tengo tres columnas llamadas person, place, thing. Puede haber personas duplicadas, lugares duplicados y cosas duplicadas, pero nunca puede haber una combinación duplicada de persona-lugar-cosa.

¿Cómo ALTERARÍA TABLA para agregar una clave primaria compuesta para esta tabla en MySQL con estas tres columnas?

David542
fuente

Respuestas:

424
ALTER TABLE provider ADD PRIMARY KEY(person,place,thing);

Si ya existe una clave principal, entonces desea hacer esto

ALTER TABLE provider DROP PRIMARY KEY, ADD PRIMARY KEY(person, place, thing);
Adrian Cornish
fuente
17
@ David542 No, no lo hace: solo puede tener 1 clave principal.
Adrian Cornish
35
@David: es una clave principal única compuesta de múltiples campos, también conocida como clave compuesta.
Marc B
3
@ David542 Por supuesto que puede, esta es una clave primaria compuesta que consta de 3 campos. La combinación de los 3 campos debe ser única.
Adrian Cornish
2
gracias por publicar - realmente me sacó de la batalla con la interfaz de
usuario
1
una de las respuestas más preciadas en SO :)
alwbtc
21

La respuesta de @Adrian Cornish es correcta. Sin embargo, hay otra advertencia para descartar una clave primaria existente. Si esa tabla principal está siendo utilizada como clave externa por otra tabla, obtendrá un error al intentar soltarla. En algunas versiones de mysql, el mensaje de error estaba mal formado (a partir de 5.5.17, este mensaje de error sigue siendo

alter table parent  drop column id;
ERROR 1025 (HY000): Error on rename of
'./test/#sql-a04_b' to './test/parent' (errno: 150).

Si desea eliminar una clave principal a la que hace referencia otra tabla, primero deberá eliminar la clave externa en esa otra tabla. Puede volver a crear esa clave externa si aún la desea después de volver a crear la clave primaria.

Además, cuando se usan claves compuestas, el orden es importante. Estas

1) ALTER TABLE provider ADD PRIMARY KEY(person,place,thing);
and
2) ALTER TABLE provider ADD PRIMARY KEY(person,thing,place);

No son lo mismo. Ambos imponen la unicidad en ese conjunto de tres campos, sin embargo, desde un punto de vista de indexación, hay una diferencia. Los campos están indexados de izquierda a derecha. Por ejemplo, considere las siguientes consultas:

A) SELECT person, place, thing FROM provider WHERE person = 'foo' AND thing = 'bar';
B) SELECT person, place, thing FROM provider WHERE person = 'foo' AND place = 'baz';
C) SELECT person, place, thing FROM provider WHERE person = 'foo' AND place = 'baz' AND thing = 'bar';
D) SELECT person, place, thing FROM provider WHERE place = 'baz' AND thing = 'bar';

B puede usar el índice de clave primaria en la declaración ALTER 1
A puede usar el índice de clave primaria en la declaración ALTER 2
C puede usar cualquiera de los índices
D no puede usar ninguno de los índices

A usa los dos primeros campos en el índice 2 como índice parcial. A no puede usar el índice 1 porque no conoce la porción del lugar intermedio del índice. Sin embargo, aún podría ser capaz de usar un índice parcial en una sola persona.

D no puede usar ninguno de los índices porque no conoce a la persona.

Vea los documentos de mysql aquí para más información.

cs_alumnus
fuente
@All: ¿podría compartir el equivalente de JPA para el mismo?
Pra_A
17

Es posible que simplemente desee una RESTRICCIÓN ÚNICA. Especialmente si ya tienes una clave sustituta. (ejemplo de una clave sustituta ya existente sería una sola columna que es un AUTO_INCREMENTO)

A continuación se muestra el código sql para una restricción única

ALTER TABLE `MyDatabase`.`Provider`
    ADD CONSTRAINT CK_Per_Place_Thing_Unique UNIQUE (person,place,thing)
;
granadaCoder
fuente
Gracias, una restricción es lo que quería, no sabía qué pedir en esta publicación inicial. Gracias por agregar esto al hilo.
ZaneDarken
Normalmente uso una clave sustituta ... luego agrego una restricción única. De esta manera ... si la "singularidad" cambia en el futuro, no es mucho drama ajustar la restricción, en lugar de jugar con la clave principal. Y si tiene tablas secundarias cuya clave externa hace referencia a esta tabla, solo tiene que FK la clave sustituta, no las 3 columnas. -
granadaCoder
3
alter table table_name add primary key (col_name1, col_name2);
Naveen Kumar Alonekar
fuente
1

Definitivamente es mejor usar COMPOSITE UNIQUE KEY, como lo ofreció @GranadaCoder, un ejemplo un poco complicado:

ALTER IGNORE TABLE table_name ADD UNIQUES INDEX idx_name(some_id, another_id, one_more_id);

Arthur Kushman
fuente
0

ALTER TABLE table_name DROP PRIMARY KEY,ADD PRIMARY KEY (col_name1, col_name2);

Suerte
fuente