7

次の(架空の)テーブルがあります。

╔════════════════════╗        ╔════════════════════╗
║ Course             ║        ║ Person             ║
╠══════╦═════════════╣        ╠══════╦═════════════╣
║ ID   ║ int         ║        ║ ID   ║ int         ║
║ Name ║ varchar(50) ║        ║ Name ║ varchar(50) ║
╚══════╩═════════════╝        ╚══════╩═════════════╝

╔════════════════════╗        ╔═════════════════════╗
║ Occupation         ║        ║ B_Occupation_Person ║
╠══════╦═════════════╣        ╠══════════════╦══════╣
║ ID   ║ int         ║        ║ Person_ID    ║ int  ║
║ Name ║ varchar(50) ║        ║ Ocupation_ID ║ int  ║
╚══════╩═════════════╝        ╚══════════════╩══════╝

╔═════════════════╗
║ B_Course_Person ║
╠═══════════╦═════╣
║ Course_ID ║ int ║
║ Person_ID ║ int ║
╚═══════════╩═════╝

Occupationテーブルには、 と の 2 つの行がありStudentますTeacher

B_Occupation_Person結合テーブルを使用すると、すべての人に職業を与えることができ、結合B_Course_Personテーブルを使用すると、教師をコースに関連付けることができます。

私の問題はB_Course_Person、教師のみを含めることができるようにしたいということです。

私の最初のアイデアは、このテーブルにチェック制約を追加することでしたが、UDF を使用してテーブルから人の職業を取得することによってのみ実行できB_Occupation_Personます。ここで読んだことから、チェック制約でUDFを使用するのは悪いことです。

Occupation私の2番目のアイデアは、テーブルに列を追加することB_Course_Personでしたが、データの冗長性が得られました...

ここで、最善の方法は何ですか?

ありがとう、

4

2 に答える 2

1

生徒と教師を区別するために個人テーブルに「タイプ」列がある場合 (たとえば、個人が両方である可能性がある場合は不可能です)、そのタイプ列を主キーに含めてから、リンク テーブルの外部キーを制限できます。教師へ:

create table person 
(
   id integer not null, 
   person_type varchar(10) not null,
   name varchar(100),
   constraint pk_person primary key (id, person_type),
   constraint type_check check (person_type in ('student', 'teacher'))
);

create table b_occupation_person
(
  occupation_id integer not null,
  person_id integer not null,
  person_type varchar(10) not null,
  constraint fk_occupation_person 
      foreign key (person_id, person_type) 
      references person (id, person_type),
  constraint type_check check (person_type = 'teacher')
);

person_type冗長ですが、b_occupation_person私が知る限り、このタイプの制約を宣言的な方法で作成する唯一のオプションです。

外部キーとチェック制約により、教師以外のものを に挿入することはできません b_occupation_person

ただし、これは実際に教師と生徒を区別できる場合 (および教師が生徒であることができない場合) にのみ機能します。

教師と生徒になる人が必要な場合(そして「person_type」がない場合) は、teacher単に person テーブルを参照するテーブルについて考えることができます。

create table person 
(
   id integer not null primary key, 
   name varchar(100)
);

create table teacher 
(
  person_id integer not null primary key,
  foreign key (person_id) references person (id)
);

create table b_occupation_person
(
  occupation_id integer not null,
  teacher_id integer not null,
  foreign key (teacher_id) references teacher (person_id)
);

これの欠点は、教師である人を 2 回 (人に 1 回、教師に 1 回) 挿入する必要があることです。

PostgreSQL では、テーブルの継承を利用して、個人から継承するように teacher を定義できます。したがって、教師に挿入すると、自動的に人も作成されます (そのような人を 2 回挿入する必要はありません)。

于 2012-08-27T18:26:12.457 に答える
0

ここでの質問は、ビジネス ロジックの形式を表しています。挿入時に b_course_person に教師のみが含まれていることを確認するだけでなく、データの一貫性を維持するという問題もあります。つまり、人が教師になるのをやめた場合、b_course_person のデータはどうなりますか?

そのため、このロジックをコードで実装する必要があります。データベースへのインターフェイスを表し、すべてのデータ変更が一貫性のある有効なデータ セットになることを保証するストアド プロシージャとして、またはビジネス ロジック レイヤー内のアプリケーションのさらに上のレイヤーとして。

于 2012-08-27T17:19:42.373 に答える