web-dev-qa-db-ja.com

複合主キーを追加するためのALTER TABLE

providerというテーブルがあります。 personplacethingという3つの列があります。人の重複、場所の重複、およびものの重複がある場合がありますが、人と場所と物の組み合わせが重複することはあり得ません。

これらの3つの列を使ってMySQLでこのテーブルの複合主キーを追加するには、どのようにALTER TABLEを実行すればよいでしょうか。

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

主キーがすでに存在する場合は、これを行います。

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

@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のドキュメント を参照してください

19
cs_alumnus

あなたは単にUNIQUE CONSTRAINTが欲しいのです。特にあなたが既に代理キーを持っているならば。 (既存の代理キーの例は、AUTO_INCREMENTである単一列です。)

下記はユニーク制約のSQLコードです。

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);

@GranadaCoderが提供していたように、COMPOSITE UNIQUE KEYを使用するほうが確実に良いでしょう。

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