このために2つのテーブルが必要な理由がいくつかわかります。
- 実際の従業員には名前、部門などが必要ですが、予測従業員にはこれらの属性しかありません
- 実際の従業員だけが負うことができる責任があるため、それらを個別に参照できるようにする必要があります
ただし、同時に、2つのテーブル間でIDの衝突が発生しないようにする必要があります。これは、(うまくいけば)予測される従業員が実際の従業員になるためです。
これを行う方法は、スーパータイプ/サブタイプの構造を実装することです。つまり、1つのテーブル、単一の主キーを保証するEMPLOYEES、および実際の従業員と予測される従業員用の2つの従属テーブルがあります。タイプ列を使用すると、特定の従業員が1つのサブテーブルにのみ表示されるようになるため、非常に重要です。
create table employees
( emp_id number not null
, emp_type varchar2(8) not null
, constraint emp_pk primary key (emp_id)
, constraint emp_uk unique (emp_id, emp_type)
, constraint emp_type_ck check (emp_type in ('FORECAST', 'ACTUAL'));
create table actual_employees
( emp_id number not null
, emp_type varchar2(8) not null
, name varchar2(30) not null
, deptno number(2,0) not null
, sal number(7,2) not null
, hiredate date not null
, constraint actemp_pk primary key (emp_id)
, constraint actemp_type_ck check (emp_type = 'ACTUAL')
, constraint actemp_emp_fk foreign key (emp_id, emp_type)
references emp (emp_id, emp_type)
deferrable initially deferred ;
create table forecast_employees
( emp_id number not null
, emp_type varchar2(8) not null
, name varchar2(30)
, deptno number(2,0)
, sal number(7,2)
, predicted_joining_date date
, constraint foremp_pk primary key (emp_id)
, constraint foremp_type_ck check (emp_type = 'FORECAST')
, constraint foremp_emp_fk foreign key (emp_id, emp_type)
references emp (emp_id, emp_type)
deferrable initially deferred ;
そのため、キーは少し奇妙に見えるかもしれません。親テーブルには、主キーと複合一意キーの両方があります。主キーは、EMP_IDの単一インスタンスを保証します。一意キーを使用すると、EMP_IDとEMP_TYPEの両方を参照する子テーブルに外部キーを作成できます。子のチェック制約と組み合わせるtこれは、主キーではなく親テーブルの一意のキーを参照するためです。この配置により、従業員はFORECAST_EMPLOYEESまたはACTUAL_EMPLOYEESのいずれかに入ることができますが、両方に入ることができません。
外部キーは、予測された従業員を実際の雇用者に変換できるように延期できます。これには3つのアクティビティが必要です:
- FORECAST_EMPLOYEESからレコードを削除する
- レコードをACTUAL_EMPLOYEESに挿入する
- EMP_TYPEを変更します(ただし、しない EMPLOYEESのEMP_ID)。
アクション2と3の同期は、制約を延期すると簡単になります。
また、EMPLOYEESを参照する他の外部キー制約では、一意キーではなく主キーを使用する必要があることに注意してください。関係が従業員のタイプを気にする場合は、代わりに子テーブルにリンクする必要があります。
データモデリングの世界へようこそ。それは1つの大きな頭痛の種です。乱雑な現実をクリーンなデータモデルに適合させようとするのは難しいからです。 :それを正しく行うには明確な要件が必要であり、賢明な妥協を行うために最も重要なことを理解する必要があります。
他の質問に基づいて、スーパータイプ/サブタイプのアプローチを提案しました。これは、実際の従業員と想定上の従業員の2つのデータセットを処理するための最良の方法であると思われるためです。これらの2つのグループは異なる方法で処理する必要があると思います。たとえば、私はマネージャーが実際の従業員であることを主張します。これは、ACTUAL_EMPLOYEESに対する整合性制約を使用すると簡単に実行でき、両方のタイプの従業員を含む単一のテーブルを使用して実現するのははるかに困難です。
確かに2つのテーブルがあるということは、それらの構造の同期に関してより多くの作業が発生する可能性があることを意味します。だから何? 1つよりも2つのALTERTABLEステートメントを作成するのはほとんど手間がかからないため、これはほとんど簡単です。さらに、新しい列が実際の従業員にのみ適用され、従業員を予測する意味がない可能性があります(EARNED_COMMISSION、LAST_REVIEW_RATINGなど)。その点で、別々のテーブルを持つことで、データモデルがより正確になります。
Ollieが指摘しているように、依存テーブルを複製する必要があることに関しては、それは誤解です。実際に関係なくすべての従業員に適用されるテーブルは、その子ではなくEMPLOYEESテーブルを参照します。
最後に、履歴データの維持が1つよりも2つのテーブルで難しい理由がわかりません。ほとんどのジャーナリングコードは、データディクショナリから完全に生成する必要があります。
3つあります テーブル:
- EMPLOYEES-一意のEMP_IDを保証するマスターテーブル
- ACTUAL_EMPLOYEES-あなたの会社で働く人々のための子テーブル
- FORECAST_EMPLOYEES-会社に採用したい人のための子テーブル
私はあなたが提供したわずかな詳細からあなたのビジネスロジックについて推測していることを覚えておいてください。
今、あなたの会社でまだ働いていない人は、関連する活動をするべきではないように私には思えます。そのシナリオでは、ACTUAL_EMPLOYEESの子であるEMPLOYEE_ACTIVITIESという1つのテーブルがあります。
しかし、おそらくあなたは本当に存在しない人々のための活動をしているのでしょう。だからここに選択肢があります:1つまたは2つのテーブル? 1つのテーブルの設計には、マスターEMPLOYEESテーブルの子としてEMPLOYEE_TASKSがあります。 2つのテーブル設計には、それぞれACTUAL_EMPLOYEESテーブルとFORECAST_EMPLOYEESテーブルの子としてACTUAL_EMPLOYEE_TASKSとFORECAST_EMPLOYEE_TASKSがあります。
どの設計が正しいかは、タスクの割り当てに関するルールを適用する必要があるかどうかによって異なります。たとえば、会社には、実際の人だけが新しいスタッフを雇うことができるというルールがある場合があります。したがって、採用タスクのみをACTUAL_EMPLOYEESに割り当てることができるモデルがあると便利です。
2つのテーブルに日付列を追加しました。これにより、必要なレポートを実行できるようになります。