複合主キーを正しく作成する方法-MYSQL


182

これは、私が作業している激しいセットアップの全体的な単純化です。table_1また、table_2どちらもIDとして自動インクリメントサロゲート主キーがあります。info両方の情報を含むテーブルがあるtable_1table_2

table_1 (id, field)  
table_2 (id, field, field)
info ( ???, field)

infoのIDの複合の主キーを作成するかどうかを決定しようtable_1としていtable_2ます。これを行うとしたら、どれが最も理にかなっていますか?
(この例では、ID 11209とID 437を組み合わせています)

INT(9)11209437 (これがなぜ悪いのか想像できます)
VARCHAR (10) 11209-437
DECIMAL (10,4)11209.437

または、他の何か?

これをMYSQL MYISAM DBの主キーとして使用しても問題ありませんか?


回答:


343

複合(複数列)キーを使用します。

CREATE TABLE INFO (
    t1ID INT,
    t2ID INT,
    PRIMARY KEY (t1ID, t2ID)
) 

このように、t1IDとt2IDを、それぞれのテーブルを指す外部キーとしても持つことができます。


2
ああ、これが複合キーの作成方法です。コンセプトを完全に誤解しているようです。ありがとうございました!!それで、このようなものは完全に索引付けの目的のためであり、それから正しいですか?このコンポジットを使用してレコードを参照することはできないので、私はまだそうする必要がありUPDATE info ... WHERE t1ID=11209 AND t2ID=437ますか?
フィリップ2011

2
正しい。両方の列は一意である必要があるため、t1ID = 11209でおそらく十分です。
AlexCuse 2011

39
@AlexCuse 両方の列の組み合わせは一意ですが、t1ID = 11209の場合、t2IDはいくつでも存在できます。
e18r 2015

21

「info」テーブルの主キーを、他のテーブルの2つの値の複合にしないでください。

他の人は理由をより明確に説明できますが、実際には2つの情報で構成される列を作成するのは間違っています。何らかの理由で2番目のテーブルのIDでソートしたい場合はどうなりますか?どちらかのテーブルの値が存在する回数をカウントしたい場合はどうでしょうか?

私は常にこれらを2つの異なる列として保持します。mysqlで2列の主キーを使用することもできます... PRIMARY KEY(id_a、id_b)...しかし、私は2列の一意のインデックスを使用し、自動インクリメント主キーフィールドを持つことを好みます。


1
明確な列を維持することは完全に正しいことです。2列の一意のインデックスを作成できることに気づかなかったので、実際にはそれが適切なオプションになると思います。なぜ主キーを自動インクリメントのままにしておくのが好きなのかと質問してもいいですか?
フィリップ2011

3
本当に説得力のある理由はありません。列が少ない方が経済的であるため、これは私と私の同僚の何人かの間の争点であると認めます。単一の外部キーで結合を書く方が簡単だと思います。これらのテーブル「2つのテーブル間のマッピング」の重要性は、元のテーブルと同じくらい重要になり、その主キーはさらに他のテーブルの外部キー列になります。
wmorse

ありがとうございました。私はあなたの言ったことは非常に理にかなっていると思うので、2列の一意のインデックス+自動インクリメントの主キーとして試してみる
フィリップ

1
私の頭の上からの理由は、あなたが関係表を作成したいからだと思います。マーケットプレイス、通貨、プロバイダーの3つのテーブルがある場合、プロバイダーはマーケットプレイスに1度しか存在できないため、リレーションシップテーブルは単一の通貨しか提供できないため、コンポジット(id_market、id_provider)は、その接続は、同じ市場とプロバイダーを一緒にもう一度追加しようとすると失敗し、それらが一意であることを意味します。次に、id_currencyなどの2番目の列があり、通貨がテーブル全体で特異であることを意味しますか?
Christopher Thomas

1
後でこのスレッドを見る人にとって、これが悪い習慣である理由は、それがデータベース設計の非常に基本的な原則に違反しているためです。第1正規形では、すべての情報に独自の列が必要です。これに違反する理由は事実上なく、データベース構造を正規化することによる複数の利点があります。
smcjones 2014年

15

構文はCONSTRAINT constraint_name PRIMARY KEY(col1,col2,col3)例えば::

CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)

上記の例は、テーブルを作成しているときに書き込みを行うと機能します。例::

CREATE TABLE person (
   P_Id int ,
   ............,
   ............,
   CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
);

この制約を既存のテーブルに追加するには、次の構文に従う必要があります

ALTER TABLE table_name ADD CONSTRAINT constraint_name PRIMARY KEY (P_Id,LastName)

8

すでにテーブルを作成しているとします。このクエリを使用して、複合主キーを作成できます。

alter table employee add primary key(emp_id,emp_name);

5

個人的な設計設定以外に、複合主キーを利用したい場合があります。テーブルには、一意の組み合わせを提供する2つ以上のフィールドが含まれる場合があり、必ずしも外部キーによるものではありません。

例として、米国の各州には一組のユニークな下院選挙区があります。多くの州が個別にCD-5を所有している場合がありますが、50州のいずれかに複数のCD-5が存在することはありません。逆も同様です。したがって、マサチューセッツCD-5の自動番号フィールドの作成は冗長になります。

データベースが動的なWebページを駆動する場合、2つのフィールドの組み合わせでクエリを実行するコードを記述することは、自動採番キーを抽出/再送信するよりもはるかに簡単です。

ですから、私は元の質問には答えていませんが、アダムの直接の答えには確かに感謝しています。


4

複合主キーは、ファクトテーブルとの多対多の関係を作成する場合に必要なものです。たとえば、多数のプロパティを含む休日のレンタルパッケージがあるとします。一方、プロパティは、単独で、または他のプロパティとともに、いくつかのレンタルパッケージの一部としても利用できる可能性があります。このシナリオでは、プロパティとパッケージのファクトテーブルを使用して、プロパティとレンタルパッケージの関係を確立します。プロパティとパッケージ間の関連付けは一意であり、property_idをプロパティテーブルと、またはpackage_idをパッケージテーブルと一緒に使用してのみ結合します。各リレーションシップは一意であり、auto_incrementキーは他のテーブルでは機能しないため冗長です。したがって、複合キーを定義することが答えです。


1
CREATE  TABLE `mom`.`sec_subsection` (

  `idsec_sub` INT(11) NOT NULL ,

  `idSubSections` INT(11) NOT NULL ,

  PRIMARY KEY (`idsec_sub`, `idSubSections`) 

);

1

@AlexCuseこれをコメントとしてコメントに追加したかったのですが、コメントに改行を追加しようとして何度も失敗したため、あきらめました。

つまり、t1IDはtable_1で一意ですが、INFOテーブルでも一意にはなりません。

例えば:

Table_1には次のものがあります:
Idフィールド
1 A
2 B

Table_2の内容
Idフィールド
1 X
2 Y

INFOには次の
値を指定できます。t1IDt2IDフィールド
1 1 some
1 2 data
2 1 ineach
2 2 row

したがって、INFOテーブルで行を一意に識別するには、t1IDとt2IDの両方が必要です


その複合キーと呼ばれる
Pavel P

1
@PavelP私の返信はwrt Alexのコメントです。「両方の列は一意でなければならないので、t1ID = 11209でおそらく十分でしょう。」...複合キーを使用することは正しいことに同意しますが、完全一致を識別するには、t1IDとt2IDの両方が必要になります...今はそれが明確であることを願っています。
sactiw 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.