13

私は、自動番号付けされた識別子を愛する Access データベースに取り組んでいました。人の名、姓、生年月日で構成されるキーを使用する 1 つを除いて、すべてのテーブルがそれらを使用しました。とにかく、リレーションシップを表すテーブルが同じリレーションシップを 2 回以上保持できるため、人々は重複に関する多くの問題に直面し始めました。関係テーブルに複合キーを実装することでこれを回避することにしましたが、それ以来、重複の問題は発生していません。

それで、Access の世界での複合キーの評判の悪さはどうなっているのだろうと思っていました。クエリを書くのは少し難しいと思いますが、少なくともフロント エンドでデータを入力したり編集したりするたびに、大量のチェックを行う必要はありません。それらは信じられないほど非効率的か何かですか?

4

9 に答える 9

12

複合キーは 1 つのテーブルに対しては問題なく機能しますが、テーブル間のリレーションを作成し始めると、少し複雑になることがあります。

2 つのテーブルPersonEvent、および と呼ばれるそれらの間の多対多の関係について考えますAppointment

Person名、姓、および生年月日で構成されるテーブルに複合キーがあり、場所Eventと名前で構成されるテーブルに複合キーがある場合、テーブルに 5 つのフィールドがありAppointment、関係を識別します。

リレーションをバインドする条件は非常に長くなります。

select Person,*, Event.*
from Person, Event, Appointment
where
  Person.FirstName = Appointment.PersonFirstName and
  Person.LastName = Appointment.PersonLastName and
  Person.BirthDate = Appointment.PersonBirthDate and
  Event.Place = Appointment.EventPlace and
  Event.Name = Appointment.EventName`.

一方、 および テーブルに自動番号付けされたキーがあるPerson場合、リレーションを識別するためEventにテーブルに必要なフィールドは 2 つだけAppointmentであり、条件ははるかに小さくなります。

select Person,*, Event.*
from Person, Event, Appointment
where
  Person.Id = Appointment.PersonId and Event.Id = Appointment.EventId
于 2010-08-18T14:09:22.060 に答える
7

SQLデータにアクセスするために純粋な自己記述のみを使用する場合、それらは問題ありません。

ただし、一部の 、アダプタなどでは、レコードを識別するためにORM単一のフィールドが必要です。PK

また、複合主キーはほぼ常に自然キーであることに注意してください (代理複合キーを作成する意味はほとんどありません。単一フィールドのものを使用することもできます)。

複合主キーの最も一般的な使用法は、多対多のリンク テーブルです。

自然キーを使用する場合は、自然キーが本質的に一意不変であることを確認する必要があります。つまり、エンティティは常にキーの同じ値で識別され、モデルに反映されると、任意の値で識別できるエンティティは 1 つだけになります。

これはあなたの場合はそうではありません。

まず、人は自分の名前や生年月日さえも変更できます

第二に、2 人John Smithsが同じ日に生まれたことは容易に想像できます。

前者は、人が名前を変更した場合、 を参照するすべてのテーブルで名前を更新する必要があることを意味しpersonsます。後者は、2 番目John Smithがデータベースに作成できないことを意味します。

あなたのようなケースでは、モデルにサロゲート識別子を追加することを本当に検討します。

于 2010-08-18T14:04:00.853 に答える
4

残念ながら、これらの否定的な意見の理由の 1 つは、おそらく無知です。候補キーの概念を正しく理解していない人が多すぎます。すべてのテーブルに必要なキーは 1 つだけであり、データの整合性には 1 つのキーで十分であり、その 1 つのキーを選択することがすべて重要であると考えているように見える人がいます。

私はしばしば、「主キー」という用語の使用を廃止し、段階的に廃止することが良いことだと推測してきました。それを行うと、データベース設計者の心は、データの正確性を確保するために必要な数のキーをテーブルに含める必要があり、それらのキーの一部はおそらく複合キーであるという実際の問題に注意を向けることになります。主キーの概念を廃止することで、主キーがどうあるべきか、どうあるべきかについての骨の折れる議論がすべてなくなります。

于 2010-08-18T18:49:04.153 に答える
3

ここで与えられた答えのほとんどは、定期的に Access を使用している人々から与えられたものではないように思われるので、その観点から意見を述べます (ただし、他の人が言ったことを繰り返しますが、一部の Access 固有のコメントのみ)。

  1. 単一列の候補キーがない場合にのみ、代理キーを使用します。これは、サロゲート PK と単一列のナチュラル PK を含むテーブルがあるが、複合キーがないことを意味します (2 つの FK の複合である結合を除き、サロゲートまたはナチュラルは関係ありません)。

  2. PK 上の Jet/ACE クラスター、および PK のみ。これには、潜在的な欠点と潜在的な利点があります (たとえば、ランダムな自動番号を PK と見なす場合)。

  3. 私の経験では、複合 PK の非 Null 要件により、潜在的に問題のあるデフォルト値を使用しない限り、ほとんどの自然キーは不可能になります。同様に、Jet/ACE で一意のインデックスを破壊するため、Access アプリ (2010 年より前) では、アプリケーションで一意性を強制することになります。A2010 以降、テーブル レベルのデータ マクロ (トリガーのように機能する) を使用して、そのロジックをデータベース エンジンに移動できる可能性があります。

  4. 複合キーは、結合を介してソース テーブルから取得する必要がある代理キーのデータを繰り返すため、結合を回避するのに役立ちます。結合はコストがかかる可能性がありますが、パフォーマンスを低下させるのは主に外部結合であり、外部結合を回避することの完全な利点が得られるのは、不要な FK のみです。しかし、正規化についてこれまでに教えられてきたことすべてに反しているように見えるので、データの繰り返しが多いことは常に私を悩ませてきました。

  5. 上で述べたように、私のアプリの唯一の複合キーは N:N 結合テーブルにあります。結合テーブル自体が関連するテーブルの親である比較的まれなケースを除いて、結合テーブルに代理キーを追加することはありません(たとえば、個人/会社の N:N レコードに関連する JobTitles、つまり、複数のジョブが含まれている可能性があります)。同じ会社です)。複合キーを子テーブルに格納するのではなく、代理キーを格納します。ただし、代理キーを PK にすることはおそらくないでしょう。複合 PK を FK 値のペアに保持します。子テーブルに結合するための一意のインデックスを持つ自動番号を追加するだけです。

思いつき次第追加します。

于 2010-08-18T23:45:47.047 に答える
1

クエリとメンテナンスが複雑になります。このテーマに本当に興味がある場合は、すでにこれをカバーしている投稿の数に目を通すことをお勧めします. これは、ここでのどの回答よりも優れた情報を提供します。

https://stackoverflow.com/search?q=composite+primary+key

于 2010-08-18T14:01:52.297 に答える
1

一部のコーダーは複雑さを認識しているがそれを避けたいと考えており、ほとんどのコーダーは複雑さを探すことさえ考えていません。

複数の候補キーを持つテーブルの一般的な例を考えてみましょう:Payrollemployee_numbersalary_amountstart_dateおよびを持つテーブルend_dateです。

4 つの候補キーは次のとおりです。

UNIQUE (employee_number, start_date); -- simple constraint 
UNIQUE (employee_number, end_date); -- simple constraint 
UNIQUE (employee_number, start_date, end_date); -- simple constraint 
CHECK (
       NOT EXISTS (
                   SELECT Calendar.day_date
                     FROM Calendar, Payroll AS P1
                    WHERE P1.start_date <= Calendar.day_date
                          AND Calendar.day_date < P1.end_date 
                    GROUP 
                       BY P1.employee_number, Calendar.day_date
                 )
      ); -- sequenced key i.e. no over-lapping periods for the same employee

これらのキーの 1 つだけを強制する必要があります。つまり、シーケンス キーです。ただし、ほとんどのコーダーはそのようなキーを追加することは考えず、そもそもそれをコーディングする方法を知っていることは言うまでもありません。実際、ほとんどの Access コーダーは、インクリメントする autonumber 列をテーブルに追加し、autonumber 列を にしPRIMARY KEY、候補キーのいずれにも制約を追加せず、自分のテーブルにキーがあると確信するだろうと思います!

于 2010-09-07T08:31:52.673 に答える