1つのテーブルに複数の主キーを含めることはできますか?
1つのテーブルに複数の主キーを含めることはできますか?
回答:
テーブルは、2つ以上の列から作成された主キーである複合主キーを持つことができます。例えば:
CREATE TABLE userdata (
userid INT,
userdataid INT,
info char(200),
primary key (userid, userdataid)
);
更新: 複合主キーの詳細な説明へのリンクがあります。
テーブルは複数の候補キーを持つことができます。各候補キーは、UNIQUEである列または列のセットであり、まとめてNOT NULLになります。したがって、任意の候補キーのすべての列に値を指定するだけで、条件を満たす行が1つあるか、まったく行がないかを判断できます。
候補キーは、リレーショナルデータモデルの基本的な概念です。
1つのテーブルに複数のキーが存在する場合、候補キーの1つを主キーとして指定するのが一般的です。また、テーブルへの外部キーが他の候補キーではなく主キーを参照するようにすることも一般的な方法です。
これらの方法をお勧めしますが、リレーショナルモデルには、候補キーの中から主キーを選択する必要があるものはありません。
これは、メインの質問と@Kalmiの質問の両方に対する回答です
複数の自動生成列があることのポイントは何ですか?
以下のコードには複合主キーがあります。その列の1つは自動インクリメントされます。これはMyISAMでのみ機能します。InnoDBはエラー「ERROR 1075(42000):Incorrect table definition; only can be only one auto column and must be defined as a key "」を生成します。
DROP TABLE IF EXISTS `test`.`animals`;
CREATE TABLE `test`.`animals` (
`grp` char(30) NOT NULL,
`id` mediumint(9) NOT NULL AUTO_INCREMENT,
`name` char(30) NOT NULL,
PRIMARY KEY (`grp`,`id`)
) ENGINE=MyISAM;
INSERT INTO animals (grp,name) VALUES
('mammal','dog'),('mammal','cat'),
('bird','penguin'),('fish','lax'),('mammal','whale'),
('bird','ostrich');
SELECT * FROM animals ORDER BY grp,id;
Which returns:
+--------+----+---------+
| grp | id | name |
+--------+----+---------+
| fish | 1 | lax |
| mammal | 1 | dog |
| mammal | 2 | cat |
| mammal | 3 | whale |
| bird | 1 | penguin |
| bird | 2 | ostrich |
+--------+----+---------+
(これまでたくさん勉強してきました)
候補キー -テーブルの行を一意に識別するために必要な最小限の列の組み合わせ。
複合キー -2つ以上の列。
ソース:
https://en.wikipedia.org/wiki/Superkey
https://en.wikipedia.org/wiki/Candidate_key
https://en.wikipedia.org/wiki/Primary_key
https://en.wikipedia.org / wiki / Compound_key
他の人が指摘したように、複数列の主キーを持つことが可能です。ただし、キーによって導入されない機能の依存関係がある場合は、関係の正規化を検討する必要があることに注意してください。
例:
Person(id, name, email, street, zip_code, area)
間の機能の依存関係が存在することができid -> name,email, street, zip_code and area
しかし、多くの場合、zip_code
関連付けられているarea
ので、間の内部機能dependecyありますzip_code -> area
。
したがって、別のテーブルに分割することを検討できます。
Person(id, name, email, street, zip_code)
Area(zip_code, name)
そのため、第3正規形と一致します。
「プライマリ」の意味合いと論理モデルに起因する潜在意識の関連付けのため、プライマリキーは非常に残念な表記法です。したがって、使用は避けます。代わりに、物理モデルのサロゲートキーと論理モデルの自然キーを参照します。
すべてのエンティティの論理モデルには、エンティティのキーを構成する「ビジネス属性」のセットが少なくとも1つあることが重要です。Boyce、Codd、Dateなどは、リレーショナルモデルでこれらを候補キーと呼びます。次に、これらのエンティティのテーブルを作成すると、それらの候補キーはそれらのテーブルの自然キーになります。ユーザーがテーブル内の行を一意に識別できるのは、これらの自然キーを介してのみです。代理キーは常にユーザーから非表示にする必要があるためです。これは、代理キーにビジネス上の意味がないためです。
ただし、テーブルの物理モデルは、多くの場合、代理キーがないと非効率になります。非クラスター化インデックスのカバーされていない列は、クラスター化インデックスへのキールックアップを通じてのみ(通常)見つけることができることを思い出してください(一時的にヒープとして実装されたテーブルは無視してください)。使用可能なNatural Keyが広い場合、これは(1)非クラスター化リーフノードの幅を広げ、非クラスター化インデックスのシークおよびスキャンに対するストレージ要件と読み取りアクセスを増加させます。(2)クラスター化インデックスからのファンアウトを減らし、インデックスの高さとインデックスサイズを増やし、クラスター化インデックスの読み取りとストレージの要件を増やします。(3)クラスタ化インデックスのキャッシュ要件を増やします。他のインデックスとデータをキャッシュから追い出します。
これは、「主キー」としてRDBMSに指定された小さなサロゲートキーが有益であることが証明される場所です。クラスタリングキーとして設定すると、非クラスタ化インデックスからクラスタ化インデックスへのキールックアップや、関連テーブルからの外部キールックアップに使用されるため、これらの欠点はすべてなくなります。クラスタ化インデックスのファンアウトは再び増加し、クラスタ化インデックスの高さとサイズを削減し、クラスタ化インデックスのキャッシュ負荷を削減し、任意のメカニズム(インデックススキャン、インデックスシーク、非クラスタ化キールックアップまたは外部キールックアップ)を介してデータにアクセスするときの読み取りを削減します。また、テーブルのクラスター化インデックスと非クラスター化インデックスの両方のストレージ要件を減らします。
これらの利点は、代理キーが小さく、クラスタリングキーの両方である場合にのみ発生することに注意してください。GUIDをクラスタリングキーとして使用すると、利用可能な最小のNaturalキーが使用された場合よりも状況が悪化することがよくあります。テーブルがヒープとして編成されている場合、8バイト(ヒープ)のRowIDがキールックアップに使用されます。これは、16バイトのGUIDよりも優れていますが、4バイトの整数よりもパフォーマンスが劣ります。
ビジネス上の制約のためにGUIDを使用する必要がある場合は、より良いクラスタリングキーを検索する価値があります。たとえば、小さなサイト識別子と4バイトの「site-sequence-number」が可能である場合、その設計は代理キーとしてのGUIDよりも優れたパフォーマンスを提供する可能性があります。
ヒープの結果(おそらくハッシュ結合)が優先ストレージになる場合、より広いクラスタリングキーのコストは、トレードオフ分析でバランスを取る必要があります。
この例を考えてみましょう::
ALTER TABLE Persons
ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
タプル「(P_Id、LastName)」は一意性制約を必要とし、長いUnicode LastName + 4バイト整数である場合があります。(1)この制約を「ADD CONSTRAINT pk_PersonID UNIQUE NONCLUSTERED(P_Id 、LastName) "および(2)小さなサロゲートキーを個別にクラスター化インデックスの" 主キー "として宣言します。注目すべきは、AnitaがLastNameをこの制約に追加したいだけなので、カバードフィールドを作成することです。すべてのフィールドがカバーされているため、クラスター化インデックスでは不要です。
SQL Serverで主キーを非クラスター化として指定する機能は、「論理モデルからの」「優先自然キーまたは候補キー」という意味と物理からの「ストレージ内のルックアップキー」という意味が混同されているため、不幸な歴史的状況です。モデル。私の理解では、元々のSYBASE SQL Serverは、物理モデルからの「ストレージ内のルックアップキー」として、ヒープまたはクラスタ化インデックスにかかわらず、常に4バイトのRowIDを使用していました。
一部の人々は、「主キー」という用語を、何らかの自動メカニズムによって生成された値を取得する整数列を正確に意味するために使用します。たとえばAUTO_INCREMENT
、MySQLまたはIDENTITY
Microsoft SQL Serverです。この意味で主キーを使用していますか?
その場合の答えは、使用しているデータベースのブランドによって異なります。MySQLでは、これを行うことはできず、エラーが発生します。
mysql> create table foo (
id int primary key auto_increment,
id2 int auto_increment
);
ERROR 1075 (42000): Incorrect table definition;
there can be only one auto column and it must be defined as a key
他のいくつかのブランドのデータベースでは、テーブルに複数の自動生成列を定義できます。
2つの主キーを同時に持つことはできません。しかし、(複合キーでケースをめちゃくちゃにしていないと仮定すると)、1つの属性を一意にすることが必要になる場合があります。
CREATE t1(
c1 int NOT NULL,
c2 int NOT NULL UNIQUE,
...,
PRIMARY KEY (c1)
);
ただし、リレーショナルデータベースでは、「スーパーキー」はテーブルのタプルまたは行を一意に識別する属性のサブセットであることに注意してください。「キー」は「スーパーキー」であり、キーから任意の属性を削除して、そのキーを「スーパーキー」ではなくする(または単に「キー」が最小のスーパーキーになる)追加のプロパティがあります。さらにキーがある場合、それらのすべてが候補キーです。候補キーの1つを主キーとして選択します。そのため、1つのリレーションまたはテーブルの複数の主キーについて話し合うことは対立します。
主キーは、レコードを一意に識別するキーであり、すべてのインデックスで使用されます。これが、1つしか持てない理由です。また、通常は子テーブルへの結合に使用されるキーですが、これは必須ではありません。PKの本当の目的は、何かがレコードを一意に識別できるようにし、データの変更が正しいレコードに影響し、インデックスを作成できるようにすることです。
ただし、1つの主キー(複合PK)に複数のフィールドを配置できます。これにより、結合が遅くなり(特に、文字列型フィールドが大きい場合)、インデックスが大きくなりますが、一部の子テーブルで結合を実行する必要がなくなる可能性があるため、パフォーマンスと設計に関しては、ケースベース。これを行う場合、各フィールド自体は一意ではありませんが、それらの組み合わせは一意です。複合キーの1つ以上のフィールドも一意である必要がある場合は、それに一意のインデックスが必要です。ただし、1つのフィールドが一意である場合、これがPKのより良い候補である可能性があります。
現在、時々、PKの候補者が複数います。この場合、PKとして1つを選択するか、代理キーを使用します(私は個人的にこのインスタンスの代理キーを好みます)。そして(これは重要です!)PKとして選択されなかった候補キーのそれぞれに一意のインデックスを追加します。データを一意にする必要がある場合は、PKであるかどうかに関係なく、一意のインデックスが必要です。これはデータの整合性の問題です。(これは、代理キーを使用する場合にも当てはまります。候補キーに一意のインデックスを作成するのを忘れているため、代理キーで問題が発生します。)
複数のサロゲートキー(必要な場合は通常はPK)が必要になる場合があります。この場合、必要なのはより多くのPKではなく、自動生成キーを持つより多くのフィールドです。ほとんどのDBではこれを許可していませんが、回避する方法はいくつかあります。最初に、2番目のフィールドが最初の自動生成キー(たとえば、Field1 * -1)に基づいて計算できるかどうか、または2番目の自動生成キーの必要性が実際に関連するテーブルの作成を意味するかどうかを検討します。関連するテーブルは、1対1の関係にあります。親テーブルから子テーブルにPKを追加し、新しい自動生成フィールドをテーブルに追加してから、このテーブルに適切なフィールドを追加することで、これを適用します。次に、2つのキーの1つをPKとして選択し、もう一方に一意のインデックスを配置します(自動生成フィールドはPKである必要はありません)。また、親テーブルにあるフィールドにFKを必ず追加してください。一般に、子テーブルに追加のフィールドがない場合は、2つの自動生成フィールドが必要であると考える理由を調べる必要があります。
良い技術的な答えは、私ができるよりも良い方法で与えられました。私はこのトピックにのみ追加できます:
許可されていない/受け入れられないものが必要な場合は、一歩戻るのがもっともです。
それが誰かを助けることを願っています。