複数の列を主キーとして使用する理由(複合主キー)


109

この例はw3schoolsからの引用です。

CREATE TABLE Persons
(
    P_Id int NOT NULL,
    LastName varchar(255) NOT NULL,
    FirstName varchar(255),
    Address varchar(255),
    City varchar(255),
    CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
)

私の理解では、両方の列(P_IdおよびLastName)は一緒にテーブルの主キーを表しますPersons。これは正しいです?

  • なぜ誰かが単一の列ではなく複数の列を主キーとして使用したいのですか?
  • 特定のテーブルで主キーとして一緒に使用できる列の数はいくつですか?


1
@Martijn Peters。なぜ回答が削除されたのですか?
PerformanceDBA、

回答:


119

あなたの理解は正しいです。

多くの場合、これを行います。1つの例は、OrderHeaderおよびのような関係OrderDetailです。のPKはかもOrderHeaderしれませんOrderNumber。PKの中にはOrderDetailあるかもしれないOrderNumberLineNumber。これらの2つのうちのいずれかである場合、それは一意ではありませんが、2つの組み合わせは一意であることが保証されます。

代わりに、この例では、生成された(インテリジェントではない)主キーを使用しますOrderDetailId。しかし、その関係を常に簡単に理解できるとは限りません。一部の人々は一方通行を好みます。一部は他の方法を好む。


2
これは、branch_idを使用していて、2つのデータベース間のレプリケーションを使用している場合、IDの重複を解決しますか?
Mhmd 2014年

11
生成された主キーを使用する多くの場合、複合値に一意のキーが必要な場合が多いことに注意してください。
ベーコンビット

「ある方法を好む人もいれば、別の方法を好む人もいます」について詳しく説明してください。
ユーザー名

1
喜ばしいですか?何を言うべきかわからない。複数の連結フィールドをキーとして使用することを好む人々を私は知っています。なぜなら、彼らが見ているものを直感的に理解する方が簡単だからです。入力が簡単かつ迅速であるため、各行に一意のキーを割り当てることを好む人もいます。それはあなたが求めていることですか?
MJB

そのメッセージは@Username宛てのものでした。指示するのを忘れました。
MJB

26

複合主キーのもう1つの例は、関連テーブルの使用です。一連の人々を含むpersonテーブルと一連のグループを含むgroupテーブルがあるとします。次に、人とグループに多対多の関係を作成します。各人が多くのグループに属することができることを意味します。複合主キーを使用した場合のテーブル構造は次のようになります。

Create Table Person(
PersonID int Not Null,
FirstName varchar(50),
LastName varchar(50),
Constraint PK_Person PRIMARY KEY (PersonID))

Create Table Group (
GroupId int Not Null,
GroupName varchar(50),
Constraint PK_Group PRIMARY KEY (GroupId))

Create Table GroupMember (
GroupId int Not Null,
PersonId int Not Null,
CONSTRAINT FK_GroupMember_Group FOREIGN KEY (GroupId) References Group(GroupId),
CONSTRAINT FK_GroupMember_Person FOREIGN KEY (PersonId) References Person(PersonId),
CONSTRAINT PK_GroupMember PRIMARY KEY (GroupId, PersonID))

素晴らしい説明:m-to-n関係(正規化されたファッション)の属性の必要性が鍵になると思います。
Wolf

多分少しの利点の説明を追加するとさらに良いでしょう
Martian2049

10

W3Schoolsの例は、複合主キーをいつ使用するべきかを示しておらず、他のキーと同じサンプルテーブルを使用した構文例のみを示しています。

それらの例の選択は、おそらく無意味なキー(P_Id)と自然キー(LastName)を組み合わせることによって、誤解を招く可能性があります。主キーのこの奇妙な選択は、次の行はスキーマに従って有効であり、学生を一意に識別するために必要であることを示しています。これは直感的には意味がありません。

1234     Jobs
1234     Gates

参考資料:優れた主キーの討論、または単にGoogle、meaningless primary keysまたはこのSOの質問を熟読する

FWIW-私の2セントは、複数列の主キーを回避し、単一の生成されたIDフィールド(代理キー)を主キーとして使用し、必要に応じて(一意の)制約を追加することです。


1
1)「大きな主キーの議論」リンクは特に愚かであり、情報は利己的で偽りです。2)行を一意にする列のインデックスは避けられません。インデックス付きの「代理」IDは、常に追加の列と追加のインデックスです。それは冗長なので、むしろばかげています。そして遅い。
PerformanceDBA、

2
「主キーの大きな議論」は愚かではありません。これは、SQL開発者やSQL DBAではなく、SQLに時間を費やしていない開発者からの非常に有効な問題です。純粋なSQLの場合でも、結合するときに主キーとして無意味な自動生成キーを使用するほうが、自然キーであるnビットのデータを渡すことを覚えておく必要があります。あなたはあなたの見方を歓迎しますが、それほど否定的ではないことを感謝します。
ロバートポールソン、

4

複数の属性の組み合わせの一意性を確保する必要がある場合は常に、複合キー(複数の属性を持つキー)を使用します。単一の属性キーは同じことを達成しません。


1
一意のキーを確保するために、2つの属性の組み合わせに依存して、論理的に複製できないキーを形成する場合があります。たとえば、より大きなデータセットからの個人と卒業日などです。
John Mark

3

はい、どちらも主キーを形成します。特にサロゲートキーがないテーブルでは、各レコードの一意の識別子として複数の属性を指定する必要がある場合があります(悪い例:名と姓の両方を持つテーブルでは、ユニーク)。


3

キーの複数の列は、通常、代理キーよりもパフォーマンスが低下します。私は代理キーを用意し、次に複数列キーに一意のインデックスを作成することを好みます。これにより、パフォーマンスが向上し、必要な独自性が維持されます。さらに、そのキーの値の1つが変更された場合、215の子テーブルの100万の子エントリを更新する必要もありません。


1
1)パフォーマンス。SQLプラットフォームではない(多分 "sql"とフリーウェアのふりをしている)。2)好みは無関係です。整合性のためにテーブルに必要なものは関連しています。3)インデックス付きの「代理」IDは、常に追加の列と追加のインデックスです。したがって、どのプラットフォームでも速度は遅くなります。パフォーマンスに関して、あなたは自分自身と矛盾しています。4)神話上の「215の子テーブルの100万の子エントリ」を適切に更新する方法がわからない場合は、質問してください。
PerformanceDBA、

2
「キー内の複数の列は、通常、代理キーよりもパフォーマンスが低下する」という文に同意しません。多くの場合、リレーションシップの代理キーを検討するときに、そのキーを取得するために追加のクエリが必要です。その時点で、それは完全に余分な往復の遅いパフォーマンスです。
ttugates

3

2番目の質問

特定のテーブルで主キーとして一緒に使用できる列の数はいくつですか?

実装固有です。使用されている実際のDBMSで定義されています。[1]、[2]、[3]使用するデータベースシステムの技術仕様を検査する必要があります。非常に詳細なものもあれば、そうでないものもあります。用語が異なるため、このような制限についてウェブを検索するのは難しい場合があります。複合主キーという用語は必須です;)

明示的な情報が見つからない場合は、テストデータベースを作成して、制限違反(予想される)の安定した(および特定の)処理を期待できることを確認してください。これに関する正しい情報を取得するように注意してください。制限が累積される場合があり、データベースレイアウトが異なると、異なる結果が表示されます。



2

複数のテーブルで主キーを使用すると、リレーショナルデータベースで中間テーブルを使用するときに便利です。

例として作成したデータベース、具体的にはそのテーブル内の3つのテーブルを使用します。数年前にウェブコミック用のデータベースを作成しました。1つのテーブルは「コミック」と呼ばれ、すべてのコミック、それらのタイトル、画像ファイル名などのリストです。主キーは「コミック」でした。

2番目のテーブルは「キャラクター」で、その名前と簡単な説明です。主キーは「charname」でした。

いくつかの例外を除いて、各コミックには複数のキャラクターがあり、各キャラクターは複数のコミックに登場したため、「キャラクター」または「コミック」のいずれかに列を入れてそれを反映することは実際的ではありませんでした。代わりに、"comicchars"と呼ばれる3つ目のテーブルを作成しました。これは、どのキャラクターがどのコミックに登場したかを示すリストでした。このテーブルは基本的に2つのテーブルを結合したため、charnameとcomicnumの2つの列が必要でしたが、主キーは両方にありました。


1

単一のレコードを構成する一意性の列値を保証するために、複合主キーを作成します。これは、重複してはならないデータの挿入を防ぐための制約です。

例:すべての学生IDと出生証明書番号が1人に一意に割り当てられている場合。次に、個人の主キーを学生IDと出生証明書番号の組み合わせにすることをお勧めします。これにより、異なる学生IDと同じ出生証明書を持つ2人を誤って挿入することが防止されるためです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.