外部キーを主キーとして使用しても問題ありませんか?


102

2つのテーブルがあります。

  • ユーザー(ユーザー名、パスワード)
  • プロフィール(profileId、gender、dateofbirth、...)

現在、私はこのアプローチを使用しています。各プロファイルレコードには、Userテーブルにリンクする外部キーとして「userId」という名前のフィールドがあります。ユーザーが登録すると、プロファイルレコードが自動的に作成されます。

私は私の友人の提案と混同しています:として「はuserId」フィールドを持っている外国人キーと「プロファイルID」フィールドを削除します。どちらのアプローチが優れていますか?


3
Entity Frameworkは、zeroOrOne(および1)対1の関係に対して(コードを最初に)生成します。だから...それは可能です。それが最善の方法ですか...それは別の質問です。しかし、それは有効です。私は自分のデータベースを作成しているときにそれをしたことはありませんでした(しかし、それを考えたことはありませんでした)。
ラファエルAlthaus

回答:


132

外部キーはほとんどの場合「重複を許可」であり、主キーとしては不適切です。

代わりに、テーブル内の各レコードを一意に識別するフィールドを見つけるか、主キーとして機能する新しいフィールド(自動インクリメント整数またはGUID)を追加します。

これに対する唯一の例外は、リンクされたテーブルの外部キーとキーが1つと同じである1対1の関係を持つテーブルです。


73
2つの外部キーで構成される複合主キーも、多対多の関係を実装するのに最適です。
右折

1
@rezadru:私にとって正しい折り方に反対することはできませんが、ほとんどの場合、代理キーの方が適しています。
Robert Harvey

4
外部キーについては、それが1対多であることを示すものはありません(または「重複を許可する」と書かれています)。キーの制約と一意性はデータベースの2つの別個の概念であり、インデックスを追加するのと同じくらい簡単に簡単に組み合わせることができます(3番目の別個の概念になります)。
ブラインドガイ

40

テーブルが1対多の関係である場合、主キーは常に一意である必要があり、外部キーは一意でない値を許可する必要があります。テーブルが1対多の関係ではなく、1対1の関係で接続されている場合は、主キーとして外部キーを使用しても問題ありません。同じユーザーレコードに複数の関連するプロファイルレコードが含まれる可能性がある場合は、別の主キーを使用します。それ以外の場合は、所有しているものを使用します。


11

はい、主キーを外部キーにすることは合法です。これはまれな構成ですが、以下に当てはまります。

  • 1:1の関係。異なる権限と特権はテーブルレベルでのみ適用されるため、2つのテーブルを1つにマージすることはできません(2017年現在、このようなデータベースは奇妙です)。

  • 1:0..1の関係。ユーザーのタイプに応じて、プロファイルが存在する場合と存在しない場合があります。

  • パフォーマンスは問題であり、デザインはパーティションとして機能します。プロファイルテーブルはめったにアクセスされない、別のディスクでホストされる、またはユーザーテーブルとは異なるシャーディングポリシーを持っています。下線付きのストレージが円柱状の場合、意味がありません。


テーブルが頻繁に結合されると、パフォーマンスが低下します。これは、1つのテーブルの方が良いという通常の推奨事項につながります。場合によっては、データは常に別々ではなく結合されてアクセスされます。また、1:1の関係にある2つのテーブルを使用することには、組織的なメリットがあります。
ブラインドガイ

4

一般に、1対1の関係を持つことは悪い習慣と考えられています。これは、データを1つのテーブルで表すだけで同じ結果を得ることができるためです。

ただし、参照しているテーブルにこれらの変更を加えることができない場合があります。この場合、外部キーを主キーとして使用しても問題はありません。自動インクリメントの一意の主キーと外部キーで構成される複合キーがあると役立つ場合があります。

現在、ユーザーがログインしてアプリで使用する登録コードを生成できるシステムに取り組んでいます。理由はわからないので、必要な列をユーザーテーブルに単純に追加することはできません。コードテーブルを使用して1対1のルートを下っていきます。


2
同じテーブル内のすべてのデータを追加の列として持つことには多くの利点があることについて、私は主に同意します。ただし、これは「1つのテーブルにデータを表示して同じ結果を得ることができる」ということですが、別のテーブルを使用すると便利です。たとえば、プロファイルテーブルのエントリがオプションの場合は、このようにします。たとえば、すべての銀行の顧客がインターネットバンキングの登録を持っているとは限りません。その場合、IB登録テーブルを使用して、他のテーブルがさらに子レコードを持つことを制限できます。ここでも、IB登録テーブルの新しいPKを使用して行うことができます。
テディ

1
@テディ同様に私はほとんどあなたが言ったことに同意します。ただし、元の質問では、「...彼のプロファイルレコードは自動的に作成されます...」とあり、プロファイルテーブルはオプションではないことを示しています。プロファイルテーブルがオプションである状況では、別のテーブルとして使用することは可能です。ただし、同じテーブルでnull許容列を使用することもできます。
Tshsmith

1
別の2番目のテーブルを使用すると、3番目のテーブルへのエントリを防ぐことができます。3番目のテーブルは、2番目のテーブルにエントリを持つ人にのみ許可されます。
テディ

もちろん、1対1のテーブルをマージすると、null値を持つユーザーが3番目の(技術的には2番目の)テーブルにアクセスできないようにすることができます。しかし、OPが尋ねた質問には、「...サインアップすると.... ...彼のプロファイルレコードは自動的に作成されます...」という行が含まれているため、これは冗長になります。
Tshsmith

これを検討する主な理由は、データウェアハウジングでは、ファクトテーブルとディメンションテーブルを分離することをお勧めします。個別のファクトテーブルとディメンションテーブルは、PowerPivot、PowerBI、Tableauなどのソフトウェアを操作するときに役立ちます。
Marco Rosas

4

はい、テーブル間の1対1の関係の場合、外部キーを主キーにすることができます


2
これは、スーパータイプ-サブタイプの設計にも役立ちます。サブタイプテーブルの主キーは、スーパータイプテーブルへの外部キー参照である必要があります。
axelioo

2

私はそれをしません。profileIDテーブルの主キーとしてを保持しますProfile

外部キーは、2つのテーブル間の単なる参照制約です

他のテーブルから参照する外部キーのターゲットとして、主キーが必要であると主張することができます。外部キーは、テーブルの1つ以上の列のセット(必ずしもそのテーブルの主キーはもちろん、候補キーである必要はありません)であり、一部の主キー列で見つかった値を保持できます。他のテーブル。したがって、外部キーと一致する主キーが必要です。それとも私たちはする必要がありますか?主キーと外部キーのペアにおける主キーの唯一の目的は、明確な結合を提供することです-参照された主キーを保持する「外部」テーブルに関して参照整合性を維持することです。これにより、外部キーが参照する値は常に有効になります(または、許可されている場合はnull)。

http://www.aisintl.com/case/primary_and_foreign_key.html


1
多分-User.UserIDとProfile.UserIDの間にFK制約がある場合、Profile.UserIDにインデックスを付けることを強くお勧めします。テーブルプロファイルのプライマリクラスター化インデックスを作成して、データベースエンジンの2番目のインデックスと不要な作業を大幅に削減してみませんか?
リバースエンジニア

1

それはビジネスとシステムに依存します。

userIdが一意であり、常に一意である場合は、userIdを主キーとして使用できます。しかし、システムを拡張したい場合は、事態が困難になります。テーブルプロファイルに外部キーを追加する代わりに、テーブルユーザーに外部キーを追加して、テーブルプロファイルとの関係を作成することをお勧めします。


0

短い答え:DEPENDS ....この特定のケースでは、問題ないかもしれません。ただし、専門家はほぼ毎回それを推奨しません。あなたのケースを含みます。

どうして?

キーが問題のテーブルに対して外部(別のテーブルで発生)である場合、キーがテーブル内で一意であることはほとんどありません。たとえば、同じタイプのアイテムが別のオーダーに存在する可能性が最も高いため、アイテムIDはITEMSテーブルでは一意であるが、ORDERSテーブルでは一意ではない場合があります。同様に、オーダーIDはORDERSテーブルでは一意(可能性があります)である可能性がありますが、ORDER_DETAILSのような他のテーブルでは複数のラインアイテムが存在する可能性があり、特定のオーダーの特定のアイテムに対してクエリを実行するには、2つの連結が必要です。このテーブルのPKとしてのFK(order_idおよびitem_id)。

私はDBの専門家ではありませんが、自動生成された値をPKとして論理的に正当化できる場合は、そうします。これが実用的でない場合は、2つ(またはそれ以上)のFKの連結がPKとして機能します。しかし、単一のFK値をPKとして正当化できるケースは考えられません。

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