provider
というテーブルがあります。 person
、place
、thing
という3つの列があります。人の重複、場所の重複、およびものの重複がある場合がありますが、人と場所と物の組み合わせが重複することはあり得ません。
これらの3つの列を使ってMySQLでこのテーブルの複合主キーを追加するには、どのようにALTER TABLEを実行すればよいでしょうか。
ALTER TABLE provider ADD PRIMARY KEY(person,place,thing);
主キーがすでに存在する場合は、これを行います。
ALTER TABLE provider DROP PRIMARY KEY, ADD PRIMARY KEY(person, place, thing);
@Adrian Cornishの答えは正しいです。ただし、既存の主キーを削除する際の注意点がもう1つあります。その主キーが別のテーブルによって外部キーとして使用されている場合、それを削除しようとするとエラーが発生します。 mysqlのいくつかのバージョンでは(5.5.17の時点で、このエラーメッセージはまだ変わっていました)
alter table parent drop column id;
ERROR 1025 (HY000): Error on rename of
'./test/#sql-a04_b' to './test/parent' (errno: 150).
他のテーブルによって参照されている主キーを削除したい場合は、まずその他のテーブルの外部キーを削除する必要があります。主キーを再作成した後も必要な場合は、その外部キーを再作成できます。
また、複合キーを使用するときは、順序が重要です。これら
1) ALTER TABLE provider ADD PRIMARY KEY(person,place,thing);
and
2) ALTER TABLE provider ADD PRIMARY KEY(person,thing,place);
同じものではありません。どちらもその3つのフィールドのセットに一意性を強制しますが、索引付けの観点からは違いがあります。フィールドは左から右にインデックスが付けられています。たとえば、次のようなクエリを考えます。
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はALTERステートメント1で主キー索引を使用できます。
AはALTERステートメント2で主キー索引を使用できます。
Cはどちらのインデックスも使用できます
Dはどちらのインデックスも使用できません
Aは、インデックス2の最初の2つのフィールドを部分インデックスとして使用します。インデックス1を使用することはできません。インデックスの中間の場所の部分がわからないためです。それでも、人だけで部分インデックスを使用できる可能性があります。
Dは人を知らないのでどちらのインデックスも使えません。
詳しくはmysqlのドキュメント を参照してください 。
あなたは単にUNIQUE CONSTRAINTが欲しいのです。特にあなたが既に代理キーを持っているならば。 (既存の代理キーの例は、AUTO_INCREMENTである単一列です。)
下記はユニーク制約のSQLコードです。
ALTER TABLE `MyDatabase`.`Provider`
ADD CONSTRAINT CK_Per_Place_Thing_Unique UNIQUE (person,place,thing)
;
alter table table_name add primary key (col_name1, col_name2);
@GranadaCoderが提供していたように、COMPOSITE UNIQUE KEYを使用するほうが確実に良いでしょう。
ALTER IGNORE TABLE table_name ADD UNIQUES INDEX idx_name(some_id, another_id, one_more_id);
ALTER TABLE table_name DROP PRIMARY KEY,ADD PRIMARY KEY (col_name1, col_name2);