私の現在のデータベース設計では、各列に任意のキーを割り当てる追加の列を作成する代わりに、複数列の主キーを使用して既存のデータ(とにかく一意)を使用しています。私はこれが許可されていることを知っていますが、これが私が慎重に使用し、おそらく回避する可能性のある慣習であるかどうか疑問に思っていました(Cのgotoのように)。
それでは、このアプローチで見られるかもしれない欠点や、単一の列キーが必要な理由は何ですか?
私の現在のデータベース設計では、各列に任意のキーを割り当てる追加の列を作成する代わりに、複数列の主キーを使用して既存のデータ(とにかく一意)を使用しています。私はこれが許可されていることを知っていますが、これが私が慎重に使用し、おそらく回避する可能性のある慣習であるかどうか疑問に思っていました(Cのgotoのように)。
それでは、このアプローチで見られるかもしれない欠点や、単一の列キーが必要な理由は何ですか?
回答:
通常、複数列の主キーを持つテーブルがある場合、それは結合テーブル(多対多)の結果であり、独自のエンティティに昇格しました(したがって、独自のプライマリキーに値します)。結合テーブルはデフォルトでエンティティである必要があると主張する人も多くいますが、それは別の日の議論です。
仮想的な多対多の関係を見てみましょう。
学生* --- *クラス
(学生は複数のクラスに属することができ、クラスは複数の学生を持つことができます)。
これらの2つのテーブルの間には、StudentClass(または記述方法に応じてClassStudent)と呼ばれるジャンクションテーブルがあります。生徒がクラスにいたときのようなものを追跡したい場合があります。したがって、StudentClassテーブルに追加します。この時点で、StudentClassは一意のエンティティになりました...そして、登録など、それを認識するために名前を付ける必要があります。
学生1 --- *登録* --- 1クラス
(学生は多くの登録を持つことができ、各登録は1つのクラス用です(または逆に、クラスが多くの登録を持つことができ、各登録は1人の学生用です)。
これで、過去1年間にChemistry 101クラスに何人の学生が登録されたかなどを照会できます。または、Acme Universityに在学中にJohn Doeが入学したクラスは何ですか?これは個別のプライマリキーなしでも可能ですが、登録用のプライマリキーを取得すると、これらの登録(IDによる)のクエリが簡単になります。合格した学生は何人ですか?
エンティティがPKに値するかどうかの判断は、そのエンティティに対して実行するクエリ(または操作)の量によって決まります。たとえば、クラスの生徒用に完了した課題を添付するとします。このエンティティ(割り当て)をアタッチする論理的な場所は、登録エンティティになります。登録を独自のプライマリキーにすると、割り当てクエリが簡単になります。
別のidカラムを持つことは理にかなっています。データベーステーブルから何かを取得したい場合は、簡単です。
SELECT whatever FROM table WHERE id=13
FROMテーブルWHERE SELECT col1 = 'val1' AND col2 = 'val2' AND col3 = 'val3'よりも
たとえば、Webアプリケーションでは、次のようなURLに変換されます。
www.somewebsite.com/somepage.php?id=13
またはこのように:
www.somewebsite.com/somepage.php?col1=val1&col2=val2&col3=val3
SELECT
クエリが発生する可能性があります。そして、B)、これが実際にどのような種類のURL要件を引き起こすのかはわかりません(悪いフレームワークで作業している場合を除く)。私のURLにはクエリ文字列が含ま?id=13
れておらず、もちろん?col1=val1&col2=val2&col3=val3
です。
基本的に、サロゲートキーを使用するかナチュラルキーを使用するかを尋ねています(この場合、コンポジットナチュラルキーのように聞こえます)。ここに素晴らしい記事があります:http : //www.agiledata.org/essays/keys.html
代理キーは、DBの存続期間中の管理を簡素化するため、代理キーを好みます(キーが意味を変えることの影響を心配する必要はありません。 ただし、DBに多くの「ルックアップ」テーブル(つまり、基本的にキーと値のペアであるテーブル)がある場合、意味のある結果を得るためにこれらのテーブルをクエリに結合する必要があるため、サロゲートキーが扱いにくくなります。
たとえば、住所と国という2つのエンティティがあるとします。
select * from Address where CountryCode = 'US'
select Address.* from Address join Country on Address.CountryID = Country.ID where Country.Code = 'US'
自然キーがあまり頻繁に変更されないことを確信していれば、ルックアップテーブルの自然キーと他のすべての代理キーを強制的に指定できます。