ALTER TABLE pour ajouter une clé primaire composite

195

J'ai une table appelée provider. J'ai trois colonnes appelées person, place, thing. Il peut y avoir des personnes en double, des lieux en double et des choses en double, mais il ne peut jamais y avoir de combinaison personne-lieu-chose en double.

Comment pourrais-je ALTER TABLE pour ajouter une clé primaire composite pour cette table dans MySQL avec ces trois colonnes?

David542
la source

Réponses:

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

Si une clé primaire existe déjà, vous souhaitez le faire

ALTER TABLE provider DROP PRIMARY KEY, ADD PRIMARY KEY(person, place, thing);
Adrian Cornish
la source
17
@ David542 Non, ce n'est pas le cas - vous ne pouvez avoir qu'une seule clé primaire.
Adrian Cornish
35
@David: c'est une seule clé primaire composée de plusieurs champs, alias une clé composite.
Marc B
3
@ David542 Bien sûr, vous pouvez - il s'agit d'une clé primaire composite composée de 3 champs. La combinaison des 3 champs doit être unique.
Adrian Cornish
2
merci d'avoir posté - ça m'a vraiment permis de ne pas me battre avec l'
interface utilisateur
1
l'une des réponses les plus précieuses dans SO :)
alwbtc
21

@Adrian Cornish a répondu correctement. Cependant, il y a une autre mise en garde à la suppression d'une clé primaire existante. Si cette clé primaire est utilisée comme clé étrangère par une autre table, vous obtiendrez une erreur en essayant de la supprimer. Dans certaines versions de mysql, le message d'erreur y était mal formé (à partir de 5.5.17, ce message d'erreur est toujours

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

Si vous souhaitez supprimer une clé primaire référencée par une autre table, vous devrez d'abord supprimer la clé étrangère dans cette autre table. Vous pouvez recréer cette clé étrangère si vous le souhaitez toujours après avoir recréé la clé primaire.

De plus, lors de l'utilisation de clés composites, l'ordre est important. Celles-ci

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

ce n'est pas la même chose. Ils imposent tous deux l'unicité sur cet ensemble de trois champs, mais du point de vue de l'indexation, il y a une différence. Les champs sont indexés de gauche à droite. Par exemple, considérez les requêtes suivantes:

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 peut utiliser l'index de clé primaire dans l'instruction ALTER 1
A peut utiliser l'index de clé primaire dans l'instruction ALTER 2
C peut utiliser l'un des index
D ne peut utiliser aucun des index

A utilise les deux premiers champs de l'index 2 comme index partiel. Un ne peut pas utiliser l'index 1 car il ne connaît pas la partie intermédiaire de l'index. Cependant, il pourrait toujours être en mesure d'utiliser un index partiel sur une seule personne.

D ne peut utiliser aucun des index car il ne connaît personne.

Voir la documentation mysql ici pour plus d'informations.

cs_alumnus
la source
@All - Pourriez-vous s'il vous plaît partager l'équivalent JPA pour le même?
Pra_A
17

Vous voudrez peut-être simplement une CONTRAINTE UNIQUE. Surtout si vous avez déjà une clé de substitution. (exemple d'une clé de substitution déjà existante serait une seule colonne qui est un AUTO_INCREMENT)

Ci-dessous le code SQL pour une contrainte unique

ALTER TABLE `MyDatabase`.`Provider`
    ADD CONSTRAINT CK_Per_Place_Thing_Unique UNIQUE (person,place,thing)
;
granadaCoder
la source
Merci, une contrainte est ce que je voulais, je ne savais pas quoi demander dans ce premier post. Merci d'avoir ajouté ceci au fil.
ZaneDarken
J'utilise généralement une clé de substitution ...... puis j'ajoute une contrainte unique. De cette façon .... si "l'unicité" change en cours de route, ce n'est pas beaucoup de drame pour modifier la contrainte, vs jouer avec la clé primaire. Et si vous avez des tables enfants dont la clé étrangère fait référence à cette table, vous n'avez qu'à FK la clé de substitution, pas les 3 colonnes. -
granadaCoder
3
alter table table_name add primary key (col_name1, col_name2);
Naveen Kumar Alonekar
la source
1

Il est certainement préférable d'utiliser COMPOSITE UNIQUE KEY, comme l'a proposé @GranadaCoder, un exemple un peu délicat cependant:

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

Arthur Kushman
la source
0

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

Chanceux
la source