web-dev-qa-db-ja.com

一般に、データベースのすべてのテーブルには、PKとして使用するIDフィールドが必要ですか?

これは私が尋ねたときでも重複しているように見えますが、検索しましたが見つかりませんでした。 SO-多くのブログなどで見つけられると確信していますが、これは良い質問のようです。SOあなたがブログで得ることができるよりも論争の。

結合で問題が発生しています。取得するレコードが多すぎます。これを「拡張」と考えています。結合のセットにテーブルを追加し、行数を拡張しました。通常、これが発生すると、結合に関係するすべてのIDフィールドの選択を追加します。そうすることで、展開がどこで発生しているかが一目瞭然で、結合のONを変更して修正できます。この場合を除いて、追加したテーブルにはIDフィールドがありません。私にとって、これは問題です。しかし、おそらく私は間違っています。

質問:データベースのすべてのテーブルに、PKとして使用されるIDENTITYフィールドが必要ですか?すべてのテーブルにIDフィールドがあることに欠点はありますか?このテーブルがPK/FK関係で使用されないことが合理的にわかっている場合はどうなりますか?

関連しますが、重複しません: ID列があることは良い考えではありませんか?

どうやらこの議論は しばらく続いている でした。知るべきだ。

この投稿 (代理キーと自然キー)も関連します。

43
jcollum

近いですが混同しないでください:IDENTITYPRIMARY KEYの2つの概念があります。

すべてのテーブル(まれな条件を除く)にはPRIMARY KEYが必要です。これは、行を一意に識別する値または値のセットです。

理由については こちら を参照してください。

IDENTITYSQL Serverの列のプロパティであり、増分値が列に自動的に入力されます。

このプロパティの性質により、この列の値は本質的にUNIQUEです。

ただし、UNIQUE制約またはUNIQUEインデックスはIDENTITY列に自動的に作成されず、SET IDENTITY_INSERT ONを発行した後、重複する値をIDENTITY列(明示的にUNIQUEが制約されていない場合)。

IDENTITY列は必ずしもPRIMARY KEYである必要はありませんが、ほとんどの場合、サロゲートPRIMARY KEYsを埋めるために使用されます

特定のケースで役立つ場合とそうでない場合があります。

したがって、あなたの質問への答え:

質問:データベースのすべてのテーブルに、PKとして使用されるIDENTITYフィールドが必要ですか?

これは:

いいえ。データベーステーブルにIDENTITYフィールドをPRIMARY KEYとして含めてはならない場合があります。

PRIMARY KEYとしてIDENTITYを使用するのが最善ではない場合、3つのケースが思い浮かびます。

  • PRIMARY KEYがコンポジットの場合(多対多のリンクテーブルなど)
  • PRIMARY KEYが自然な場合(州コードなど)
  • PRIMARY KEYがデータベース全体で一意である必要がある場合(この場合はGUID/UUID/NEWIDを使用します)

これらのすべてのケースは、次の状態を意味します。

PRIMARY KEYの値を気にし、それらを明示的にテーブルに挿入する場合は、IDENTITYを使用しないでください。

更新:

多対多リンクテーブルには、複合キーとしてリンクするテーブルへのidのペアが必要です。

これは、既に使用している(そしてUNIQUEを作成する)必要がある自然な複合キーなので、このための代理キーを生成する意味はありません。

リンクするテーブル以外の他のテーブルからmany-to-manyリンクテーブルを参照する理由はわかりませんが、そのようなニーズがあると仮定しましょう。

この場合、複合キーによってリンクテーブルを参照するだけです。

このクエリ:

CREATE TABLE a (id, data)
CREATE TABLE b (id, data)
CREATE TABLE ab (a_id, b_id, PRIMARY KEY (a_id, b_id))
CREATE TABLE business_rule (id, a_id, b_id, FOREIGN KEY (a_id, b_id) REFERENCES ab)

SELECT  *
FROM    business_rule br
JOIN    a
ON      a.id = br.a_id

これよりもはるかに効率的です:

CREATE TABLE a (id, data)
CREATE TABLE b (id, data)
CREATE TABLE ab (id, a_id, b_id, PRIMARY KEY (id), UNIQUE KEY (a_id, b_id))
CREATE TABLE business_rule (id, ab_id, FOREIGN KEY (ab_id) REFERENCES ab)

SELECT  *
FROM    business_rule br
JOIN    a_to_b ab
ON      br.ab_id = ab.id
JOIN    a
ON      a.id = ab.a_id

、明白な理由で。

61
Quassnoi

ほとんど常にはい。やむを得ない理由がない限り、私は通常、デフォルトでIDフィールドを含めます。このような理由に遭遇することはめったになく、IDフィールドのコストは最小限であるため、通常は含めます。

重要なリレーショナルモデリング以外のほぼすべての機能にDBMSが使用されているリレーショナルデータベースよりも、データストアとして使用されている高度に専門化されたデータベースではなかったのは、頭の中で思い浮かんだことだけです。 (それは大量の高回転データバッファーのことでした。)

14
Greg D

私は多くの場合、自然なキーは人工的なキーよりもはるかに悪いと信じています。なぜなら、キーを変更して、データの整合性やパフォーマンスに重大な問題を引き起こす可能性があるかどうかを制御できないことが多いからです。

ただし、IDフィールドでなくても意味のあるいくつかの(ごく少数の)自然キーがあります(2文字の州の省略形が頭に浮かびます。これらの公式の型省略形が変更されることは非常にまれです)。

多対多の関係をモデル化する結合テーブルであるテーブルは、おそらく追加のIDフィールドも必要ありません。 2つのキーフィールドを一緒に主キーにすると、問題なく動作します。

それ以外は、特定の場合にやむを得ない理由が与えられない限り、他のほとんどのテーブルにIDフィールドを追加します。テーブルに主キーを作成できない場合や、代理キーを使用して、可能な限り一意性を保証するために必要な他のフィールドに一意のインデックスを配置できない場合は、悪い方法です(重複を実際に解決しない限り)。

12
HLGEM

すべてのテーブルには、それを一意に識別するフィールドのセットが必要です。データフィールドとは別の数値識別子フィールドがあるかどうかは、モデル化しようとしているドメインによって異なります。すべてのデータが簡単に「単一の数値ID」パラダイムに該当するわけではないため、データを強制することは不適切です。それを考えると、多くのデータがこのパラダイムに簡単に適合し、そのような識別子が必要になります。どのプログラミング環境でも常にXを実行する答えは1つではありません。これは別の例です。

4
Mark Roddy

いいえ。人工ID列を持つテーブルがある場合は常に、テーブルの自然な主キーを識別し、その列のセットにも一意の制約があることを確認して、2つの行が取得されないようにする必要があります。偶然に無意味なID列を除いて同一です。

ID列の追加は無料です。不要なID列をテーブルに追加すると、オーバーヘッドが発生します。通常、ID値のストレージの行ごとに4バイトと、追加のインデックス全体(行あたり8〜12バイトとオーバーヘッドの合計)になります。また、テーブルごとに追加のインデックスがあるため、最も費用対効果の高いクエリプランを作成するのに少し時間がかかります。確かに、テーブルが小さく、マシンが大きい場合、このオーバーヘッドは重要ではありませんが、最大のシステムでは重要です。

4

モデル化、設計、正規化などを行っている場合、ID列はありません。

テーブルの自然キーと候補キーを識別しました。

たとえば、nvarchar(100)列を使用するのは良い考えではない(まだ一意の制約が必要)ため、物理アーキテクチャ(狭い、数値、厳密に単調増加など)のために、代理キーを決定できます。

またはイデオロギーのため:OO私が見つけた開発者にアピールします。

では、ID列を想定します。データベースがより複雑になると、たとえばいくつかのレイヤーで、親テーブルとgrand-.childテーブルを直接結合する方法を説明します。できません。常に中間テーブルと適切にインデックス付けされたPK-FL列が必要です。複合キーがあれば、すべてが揃います...

誤解しないでください。私はそれらを使用しています。しかし、なぜ私はそれらを使うのか知っています...

編集:

一方で「常にID」+「ストアドプロシージャなし」の一致を照合し、もう一方で「ストアドプロシージャを使用」+「IDのメリットがある場合」を照合することに興味があります...

3
gbn

Identityフィールドとキーの違いを認識してください...同じ「エンティティ」を表す複数の行を誤って入力することによるデータの破損を排除するには、すべてのテーブルにキーが必要です。テーブルにある唯一のキーが無意味な代理キーである場合、この関数は事実上欠落しています。

otoh、テーブルがIDを「必要とする」ことはなく、すべてのテーブルが1つのメリットを享受するわけではありません...例は次のとおりです。別のテーブルと1対0または1の関係にあるテーブル...これらはどれもIDを必要としません

1
Charles Bretana

各テーブルにIDフィールドがあることの欠点は考えられません。 IDフィールドのタイプを指定すると、テーブルを拡張するための十分なスペースが提供されます。

ただし、行のIDを確認するために必ずしも単一のフィールドが必要なわけではありません。したがって、いいえ単一のIDフィールドは必須ではありません

プライマリおよび外部Keysは、1つのフィールドだけでなくmultiple fieldsで構成できます。これは、N-N関係を実装するテーブルでは一般的です。

あなたはあなたのテーブルに完全にPRIMARY KEY (fa, fb)を持つことができます:

CREATE TABLE t(fa INT , fb INT);
ALTER TABLE t ADD PRIMARY KEY(fa , fb);
1
jeje

はい、ほとんどの場合。

エッジケースまたは例外は次のようなものです。

  • m:n関係をモデル化するための双方向結合テーブル
  • 大量のデータを一括挿入するために使用される一時テーブル

しかし、それ以外は、テーブルの各行を一意に識別するために主キーを使用することには十分な理由はないと思います。私の意見では、IDENTITYフィールドを使用するのが最良の選択の1つです(自然キーよりも代理キーを使用することをお勧めします-それらはより信頼性が高く、安定しており、決して変更されないなど)。

マーク

1
marc_s

テーブルに単純で自然なキー(1つの列)が見つかった場合は、ID列の代わりにそれをキーとして使用します。

自然なものでも生成されたものでも、通常はすべてのテーブルに特定の種類の一意の識別子を付けます。これは、すべての行が何らかの方法で一意に識別される保証だからです。

個人的には、疫病のようなIDENTITY(1、2、3、4のようなID列の増加)列は避けます。特にテーブルから行を削除する場合は、多くの手間がかかります。テーブルに自然キーがない場合は、代わりに生成されたuniqueidentifiersを使用します。

とにかく、これが受け入れられている慣行であるかどうかはわかりませんが、私には正しいようです。 YMMV。

0
Matthew Jones