現在、新しいデータベースを設計しています。学校では、各テーブルに主キーを配置することを常に学びました。
PK の代わりに一意の制約 (一部のデータベースの一意のインデックス) を使用する方が良いという記事/ディスカッション/ニュースグループの投稿をたくさん読みました。
あなたの視点は何ですか?
現在、新しいデータベースを設計しています。学校では、各テーブルに主キーを配置することを常に学びました。
PK の代わりに一意の制約 (一部のデータベースの一意のインデックス) を使用する方が良いという記事/ディスカッション/ニュースグループの投稿をたくさん読みました。
あなたの視点は何ですか?
主キーは、実際には NULL を許可しない単なる候補キーです。そのため、SQL 用語では、他の一意のキーと何ら変わりはありません。
ただし、理論に基づかない RDBMS の場合は、プライマリ キーを使用する必要があります。そうでないと主張されているのは聞いたことがありません。その主キーが代理キーである場合、自然キーにも一意の制約が必要です。
重要な点は、すべての候補 (自然キーまたは代理キー)に一意の制約を設定する必要があるということです。次に、外部キーで最も参照しやすいものを主キーとして選択する必要があります*。
クラスター化インデックスも必要です*。これは主キーまたは自然キーのいずれかですが、必須ではありません。テーブルのクエリの使用状況に基づいてクラスター化インデックスを選択する必要があります。疑わしい場合は、主キーを最初に選択することをお勧めします。
技術的には、外部キーの関係で一意のキーを参照することだけが必要ですが、主キーを大いに優先することが標準的な慣行として受け入れられています。実際、一部の RDBMS で主キーの参照のみが許可されていても驚かないでしょう。
編集: Oracle の「クラスター化されたテーブル」と「クラスター化されたインデックス」という用語は、Sql Server とは異なることが指摘されています。私がOracle-eseで話しているのと同等のものはIndex Ordered Tableであり、OLTPテーブルに推奨されます.SOの質問の主な焦点になると思います. 大規模な OLAP データ ウェアハウスを担当している場合は、データベースの設計と最適化についてすでに独自の意見を持っているはずです。
これらの記事への参照を提供できますか?
実証済みの真の方法を変更する理由はありません。結局、主キーはリレーショナル データベースの基本的な設計機能です。
UNIQUE を使用して同じ目的を果たすことは、私には本当にハックに聞こえます。彼らの論理的根拠は何ですか?
編集:私の注意は、この古い答えに引き戻されました。おそらく、PK と UNIQUE に関して読んだ議論は、一意性を強制するという唯一の目的で何かを PK にする人々を扱ったものでしょう。これに対する答えは、それがキーである場合はキーにし、そうでない場合は一意にすることです。
主キーは、特別な処理 (インデックスの自動作成など) のために選択された単なる候補キー (一意の制約) です。
それらに異議を唱える人々は、ある鍵を別の鍵とは異なる方法で扱う理由を理解していないと思います。それが私が立っているところです。
[編集] 50 点がないと、自分の回答でもコメントできないようです。
@chris: 害はないと思います。「主キー」は、実際には単なるシンタックス シュガーです。いつも使っていますが、絶対に必要だとは思いません。はい、一意のキーが必要ですが、必ずしも主キーである必要はありません。
主キーのないテーブルが必要になる非正規化は非常にまれです。主キーには、PK としての性質だけで自動的に一意の制約があります。
一意性制約は、主キーへの追加で列の一意性を保証する場合に使用されます。
常に PK を持つというルールは良いルールです。
常に主キーが必要です。
ただし、あなたの質問は少し誤解を招く表現であると思われます。実際には、主キーを常に自動生成された番号(代理キーとも呼ばれます)にするか、実際に意味のあるデータである一意のフィールド(自然キーとも呼ばれます)にするかを尋ねる必要があります。キー)、人のSSN、本のISBNなど。
この質問は、DB分野における古くからの宗教戦争です。
私の考えでは、自然キーは、実際に一意であり、変更されない場合に適しています。ただし、特定の状況では、人のSSNのように安定しているように見えるものでも変更される可能性があるため、注意が必要です。
テーブルが作業中にデータをステージングするための一時テーブルでない限り、常にテーブルに主キーを配置する必要があります。その理由は次のとおりです。
1 - 一意の制約では null が許可されますが、主キーでは null は許可されません。null 値を持つ列に対して結合を使用してクエリを実行すると、null は null と等しくないため、結果のデータ セットからそれらの行が削除されます。これは、大企業でさえ会計上の誤りを犯し、利益を再表示しなければならない方法です。一意のインデックスの一部の列に NULL 値があったため、クエリは合計に含まれるべき特定の行を表示しませんでした。主キーを使用する必要がありました。
2 - 一意のインデックスが主キーに自動的に配置されるため、作成する必要はありません。
3 - ほとんどのデータベース エンジンは、クラスター化されたインデックスを主キーに自動的に配置し、行がデータ ブロックに連続して格納されるため、クエリが高速になります。(クエリを高速化する場合は、クラスター化インデックスを別のインデックスに配置するように変更できます。) テーブルにクラスター化インデックスがない場合、行はデータ ブロックに連続して格納されず、クエリが読み取り/書き込みヘッドがデータを取得するためにディスク全体を移動する必要があるため、速度が低下します。
4 - 多くのフロントエンド開発環境では、テーブルを更新したり削除したりするために主キーが必要です。
主キーは、このテーブルからこの値を参照する他のテーブルへの関係を確立する状況で使用する必要があります。ただし、一意制約を適用しようとしているテーブルとデータの性質によっては、代理キーを確立するのではなく、その特定のフィールドを自然な主キーとして使用できる場合があります。もちろん、代理キーと自然キーはまったく別の議論です。:)
このテーブルと他のテーブルの間に関係が確立されない場合は、一意のキーを使用できます。たとえば、新しいユーザー レコードなどを挿入する前に比較される有効な電子メール アドレスのリストを含むテーブルです。または、テーブルに主キーがあり、完全に一意である必要がある値がある場合は、一意のキーを使用できます。たとえば、ユーザー名を持つ users テーブルがあるとします。ユーザー名を主キーとして使用することは望ましくありませんが、ログイン目的で使用するためには一意である必要があります。
ここでは、論理構成と物理構成を区別する必要があります。同様に、理論と実践も区別する必要があります。
まず、理論的な観点から、主キーがない場合、テーブルはありません。とても簡単です。したがって、問題は、テーブルに主キーを含める必要があるかどうかではなく(もちろん、そうする必要があります)、RDBMS内でどのようにラベル付けするかです。
物理レベルでは、ほとんどのRDBMSは主キー制約を一意のインデックスとして実装します。選択したRDBMSがこれらのいずれかである場合、列を主キーとして指定することと、単に列に一意の制約を設定することとの間には、おそらくそれほど実用的な違いはありません。ただし、これらのオプションの1つは意図をキャプチャし、もう1つはキャプチャしません。したがって、決定は簡単です。
さらに、一部のRDBMSは、主キーに適切なラベルが付けられている場合に、ダイアグラム作成や半自動化された外部キー制約のサポートなどの追加機能を利用できるようにします。
一般的なルールとして主キーの代わりに一意の制約を使用するように指示する人は、かなりひどい正当な理由を提供する必要があります。
PKの代わりに一意性制約(一部のデータベースの一意性インデックス)を使用する方がよいという投稿
ここでの唯一のポイントは、同じ古い議論「自然キーと代理キー」であると思います。これは、一意のインデックスとpkが同じものであるためです。
翻訳:
代理キーの代わりに自然キーを使用する方がよいという投稿
私はこのテーマについて多くのことを書いてきました: もしあなたが私の記事を読んでいるなら、私が特に Jet 別名 MS Access について言及していたことを明確にしておいてください。
Jet では、テーブルは、メンテナンスされていないクラスター化インデックスを使用して PRIMARY KEY で物理的に順序付けられます (コンパクトでクラスター化されます)。テーブルに PK がないが、NOT NULL 列で UNIQUE 制約を使用して定義された候補キーがある場合、エンジンはクラスター化インデックス用に 1 つを選択します (テーブルにクラスター化インデックスがない場合、それはヒープと呼ばれ、おそらくまったくテーブルではありません) !) エンジンはどのように候補キーを選択しますか? null 許容列を含むものを選択できますか? 本当にわかりません。ポイントは、Jet でクラスター化インデックスをエンジンに明示的に指定する唯一の方法は、PRIMARY KEY を使用することです。もちろん、Jet の PK には他にも用途があります。たとえば、SQL DDL の FOREIGN KEY 宣言から 1 つが省略された場合にキーとして使用されますが、ここでも明示しない理由があります。
Jet の問題点は、テーブルを作成するほとんどの人がクラスター化インデックスを認識していないか、関心がないことです。実際、ほとんどのユーザー (私は賭けます) は、すべてのテーブルに自動インクリメント Autonumber 列を配置し、この列のみに PRIMARY KEY を定義しますが、自然キーと候補キーに一意の制約を設定することはできません (自動インクリメント列が実際にエンドユーザーに公開しないキーは、それ自体が別の議論です)。ここではクラスター化インデックスについて詳しくは説明しませんが、IMO が唯一の自動インクリメント カラムであることが理想的な選択になることはめったにないと言っておけば十分です。
SQL エンジンが何であれ、PRIMARY KEY の選択は任意であり、エンジン固有です。通常、エンジンは PK に特別な意味を適用します。そのため、それが何であるかを調べて、有利に使用する必要があります。特に、データ モデルで意味を持たない (べきではない) 'autonumber' 列を使用することを選択した場合は、すべての候補キーに十分な考慮を払うことを期待して、NOT NULL UNIQUE 制約を使用することをお勧めします。しかし、習慣から自動インクリメント列に置くのではなく、よく考えられたキーを 1 つ選択し、PRIMARY KEY を使用したいと思います。
すべてのテーブルに PK が必要ですか? そうしないと、少なくともエンジンが PK に提供するわずかな利点を逃し、最悪の場合、データの整合性が失われるため、私はそう言います。
BTW Chris OC は、単純な PRIMARY KEY 制約 (大文字の SQL キーワード) では実装できない、順序付けられた主キー (小文字) を必要とするテンポラル テーブルについて、ここで良い点を指摘しています。
私は通常、PK と UNIQUE KEY の両方を使用します。スキーマで PK を指定しなくても、常に内部で PK が生成されるためです。これは、SQL Server 2005 と MySQL 5 の両方に当てはまります。
しかし、SQL では PK 列を使用しません。これは、誤った行を削除したり、AUTO INCREMENT に設定されている場合に PK 値間のギャップを見つけたりするなどの管理目的のためです。また、列や文字配列のセットではなく、数値として PK を使用することは理にかなっています。
主キー
1. Null Null 値を許可しません。このため、PRIMARY KEY = UNIQUE KEY + Not Null CONSTRAINT を参照します。 2. INDEX デフォルトでは、クラスター化インデックスが追加されます。 3. LIMIT テーブルは、1 つの PRIMARY KEY 列のみを持つことができます。
ユニークキー
1. Null Null 値を許可します。ただし、Null 値は 1 つだけです。 2. INDEX デフォルトでは、UNIQUE 非クラスター化インデックスが追加されます。 3. LIMIT テーブルには、複数の UNIQUE キー列を含めることができます。
問題は、主キーが、テーブルの単一のレコードを一意に識別する 1 つ以上の列である可能性があることです。ここで、一意の制約は、テーブル内の特定のデータ要素の単一のインスタンスのみを許可するフィールドの制約にすぎません。
個人的には、テーブル間の相互参照に使用される一意のキーに、GUID または自動インクリメント BIGINTS (SQL SERVER の ID 挿入) を使用しています。次に、他のデータを使用して、ユーザーが特定のレコードを選択できるようにします。
たとえば、従業員のリストがあり、バックグラウンドで使用するすべてのレコードに GUID が関連付けられていますが、ユーザーが従業員を選択するときは、次のフィールドに基づいて従業員を選択しています: LastName + FirstName + 従業員番号。
このシナリオの主キーは LastName + FirstName + EmployeeNumber で、一意のキーは関連する GUID です。
LINQ-to-SQL の使用を計画している場合、更新の実行を計画している場合はテーブルに主キーが必要ですtimestamp
。切断された環境 (WCF サービス アプリケーションを介してオブジェクトを渡すなど) で作業する場合は、列が必要です。 )。
.NET が好きなら、PK と FK は友達です。
私はあなたが両方を必要とするかもしれないことを提出します. 本質的に、主キーは一意である必要があり、null 可能ではありません。整数は文字フィールドよりも高速な結合を作成し、特に複数フィールドの文字結合よりも高速な結合を作成するため、これらは多くの場合代理キーです。ただし、これらは自動生成されることが多いため、ID 自体を除くデータ レコードの一意性は保証されません。テーブルに一意である必要がある自然キーがある場合は、データ入力の重複を防ぐために一意のインデックスを作成する必要があります。これは、基本的なデータ整合性の要件です。
編集して追加: 特にデータベースが人中心の場合、現実世界のデータには、正規化されたテーブル構造で一意性を真に保証する自然キーがないことが多いことも現実の問題です。名前、住所、電話番号を組み合わせても (同じ医療行為の父と息子を考えてください)、必ずしも一意であるとは限りません。
私はこの問題を自分で考えていました。ユニークを使っていると2.NFを痛めます。これによると、すべての非 pk 属性は PK に依存する必要があります。この一意の制約の属性のペアは、PK の一部と見なされます。
7年後に返信して申し訳ありませんが、新しい議論を始めたくありませんでした.