web-dev-qa-db-fra.com

ALTER TABLE pour ajouter une clé primaire composite

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 dupicate personne-lieu.

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

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

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

ALTER TABLE provider DROP PRIMARY KEY, ADD PRIMARY KEY(person, place, thing);
398
Adrian Cornish

La réponse de @Adrian Cornish est correcte. Cependant, il y a une autre mise en garde à faire pour supprimer 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 était mal formé (à partir du 5.5.17, ce message d’erreur est toujours affiché).

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 devez commencer par supprimer la clé étrangère de 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, lorsque vous utilisez des 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);

ne sont pas la même chose. Ils imposent l'unicité sur cet ensemble de trois champs, mais il existe une différence du point de vue de l'indexation. Les champs sont indexés de gauche à droite. Par exemple, considérons 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 ou l'autre index
D ne peut utiliser ni l'index

A utilise les deux premiers champs de l'index 2 comme index partiel. A ne peut pas utiliser l'index 1, car il ne connaît pas la partie de l'index située à l'emplacement intermédiaire. Cependant, il pourrait toujours utiliser un index partiel sur une personne juste.

D ne peut utiliser l’un ou l’autre index car il ne connaît pas la personne.

Voir la documentation mysql ici pour plus d'informations.

19
cs_alumnus

Vous voudrez peut-être simplement une contrainte unique. Surtout si vous avez déjà une clé de substitution. (un exemple de clé de substitution déjà existante serait une colonne unique 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)
;
15
granadaCoder
alter table table_name add primary key (col_name1, col_name2);
3

Il est certainement préférable d’utiliser COMPOSITE UNIQUE KEY, comme le propose @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);

1
Arthur Kushman

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

0
Lucky