Виждам няколко причини да имате нужда от две таблици за това:
- реалните служители трябва да имат име, отдел и т.н., докато само прогнозните служители могат да имат тези атрибути
- ще има отговорности, които могат да имат само истински служители, така че искате да можете да ги посочите отделно
Но в същото време искате да сте сигурни, че няма сблъсък на идентификатори в двете таблици, защото (надявам се) прогнозните служители ще станат действителни служители.
Начинът да направите това е да приложите структура на супер-тип/подтип. Така че имате една таблица, EMPLOYEES, която гарантира единични първични ключове, и две зависими таблици за действителни и прогнозни служители. Използването на колоната тип е от решаващо значение, тъй като гарантира, че даден служител се появява само в една подтаблица.
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, но не и двете.
Външните ключове могат да бъдат отложени, за да позволят преобразуването на прогнозните служители в действителни служители. Това изисква три дейности:
- изтриване на записа от FORECAST_EMPLOYEES
- вмъкване на запис в ACTUAL_EMPLOYEES
- промяна на EMP_TYPE (но не EMP_ID) в EMPLOYEES.
Синхронизирането на действия 2 и 3 е по-лесно с отложени ограничения.
Също така имайте предвид, че други ограничения на външен ключ, отнасящи се до EMPLOYEES, трябва да използват първичния ключ, а не уникалния ключ. Ако връзката се интересува от вида на служителя, вероятно вместо това трябва да се свърже към дъщерните таблици.
Добре дошли в света на моделирането на данни. Това е едно голямо главоболие. Защото опитът да се вмести обърканата реалност в чист модел на данни е трудно :имате нужда от ясни изисквания, за да го направите правилно, и разбиране на най-важното, за да можете да правите разумни компромиси.
Предложих подход на супертип/подтип въз основа на другия ви въпрос и защото изглежда, че това е най-добрият начин за обработка на два набора от данни:реални служители и условни служители. Мисля, че тези две групи трябва да бъдат третирани по различен начин. Например, бих настоял мениджърите да бъдат истински служители. Това е лесно да се направи с ограничение за интегритет срещу ACTUAL_EMPLOYEES и много по-трудно за постигане с една таблица, която съдържа и двата типа служители.
Разбира се, наличието на две таблици означава, че вероятно генерира повече работа по отношение на синхронизирането на техните структури. Какво от това? До голяма степен е тривиално, тъй като е малко повече работа да напишете два оператора ALTER TABLE от един. Освен това е напълно възможно новата колона да се отнася само за действителни служители и да няма значение за прогнозиране на служители (напр. EARNED_COMMISSION, LAST_REVIEW_RATING). В тази светлина наличието на отделни таблици прави модела на данните по-точен.
По отношение на необходимостта от дублиране на зависими таблици, както посочва Оли, това е недоразумение. Таблиците, които се отнасят за всички служители, независимо от тяхната актуалност, трябва да препращат към таблицата EMPLOYEES, а не към нейните деца.
И накрая, не разбирам защо поддържането на исторически данни е по-трудно с две таблици, отколкото с една. Повечето журналиращи кодове трябва да бъдат изцяло генерирани от речника на данните.
Има три таблици:
- EMPLOYEES - главна таблица за гарантиране на уникални EMP_ID
- ACTUAL_EMPLOYEES - дъщерна таблица за хора, които работят за вашата компания
- FORECAST_EMPLOYEES - дъщерна таблица за хора, които се надявате да наемете във вашата компания
Моля, имайте предвид, че правя предположения за вашата бизнес логика от оскъдните подробности, които предоставихте.
Сега ми се струва, че хората, които все още не работят за вашата компания, не трябва да имат свързани дейности. В този сценарий ще имате една таблица, EMPLOYEE_ACTIVITIES, която е дъщерна на ACTUAL_EMPLOYEES.
Но може би наистина имате дейности за хора, които не съществуват. И така, ето избор:една маса или две? Дизайнът на една таблица има EMPLOYEE_TASKS като дете на главната таблица EMPLOYEES. Дизайнът на двете таблици има ACTUAL_EMPLOYEE_TASKS и FORECAST_EMPLOYEE_TASKS като деца съответно на таблиците ACTUAL_EMPLOYEES и FORECAST_EMPLOYEES.
Кой дизайн е правилният зависи от това дали трябва да наложите правила относно възлагането на задачи. Например, вашата компания може да има правило, което гласи, че само истински хора могат да наемат нов персонал. Така че би било полезно да има модел, който позволява само задачи за набиране на персонал да бъдат възлагани на ACTUAL_EMPLOYEES.
Добре, добавих колони с дати към двете таблици. Това ще ви позволи да стартирате отчета, който искате.