Vedo un paio di motivi per cui hai bisogno di due tabelle per questo:
- I dipendenti reali devono avere un nome, un dipartimento ecc., mentre solo i dipendenti previsti possono avere questi attributi
- Ci saranno responsabilità che solo i veri dipendenti possono avere, quindi vuoi essere in grado di farvi riferimento separatamente
Ma allo stesso tempo vuoi assicurarti che non ci siano scontri di ID tra le due tabelle, perché (si spera) i dipendenti previsti diventeranno dipendenti effettivi.
Il modo per farlo è implementare una struttura di super-tipo/sottotipo. Quindi hai una tabella, EMPLOYEES che garantisce chiavi primarie singole e due tabelle dipendenti per i dipendenti effettivi e previsti. L'uso della colonna tipo è fondamentale, in quanto garantisce che un determinato dipendente appaia solo in una sottotabella.
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 ;
Quindi le chiavi potrebbero sembrare un po' strane. La tabella padre ha sia una chiave primaria che una chiave univoca composta. La chiave primaria garantisce una singola istanza di EMP_ID. La chiave univoca ci consente di costruire chiavi esterne sulle tabelle figlie che fanno riferimento sia a EMP_ID che a EMP_TYPE. Combinato con i vincoli di controllo sul figlio tQuesto perché fanno riferimento alla chiave univoca sulla tabella padre piuttosto che alla sua chiave primaria. Questo accordo garantisce che un dipendente possa essere in FORECAST_EMPLOYEES o ACTUAL_EMPLOYEES ma non in entrambi.
Le chiavi esterne sono differibili per consentire la conversione dei dipendenti previsti in dipendenti effettivi. Ciò richiede tre attività:
- eliminando il record da FORECAST_EMPLOYEES
- inserimento di un record in ACTUAL_EMPLOYEES
- modifica EMP_TYPE (ma non l'EMP_ID) in EMPLOYEES.
La sincronizzazione delle azioni 2 e 3 è più semplice con i vincoli posticipati.
Si noti inoltre che altri vincoli di chiave esterna che fanno riferimento a EMPLOYEES dovrebbero utilizzare la chiave primaria anziché la chiave univoca. Se la relazione si preoccupa del tipo di dipendente, probabilmente dovrebbe invece collegarsi alle tabelle figlio.
Benvenuti nel mondo della modellazione dei dati. È un grande mal di testa. Perché cercare di adattare una realtà disordinata a un modello di dati pulito è difficile :sono necessari requisiti chiari per farlo bene e una comprensione di ciò che conta di più in modo da poter scendere a compromessi sensati.
Ho proposto un approccio di super-tipo/sottotipo sulla base dell'altra tua domanda e perché sembra essere il modo migliore per gestire due insiemi di dati:dipendenti reali e dipendenti fittizi. Penso che questi due gruppi debbano essere trattati in modo diverso. Ad esempio, insisterei sul fatto che i manager siano dei veri dipendenti. Questo è facile da fare con un vincolo di integrità contro ACTUAL_EMPLOYEES e molto più difficile da ottenere con una singola tabella che contiene entrambi i tipi di dipendenti.
Sicuramente avere due tabelle significa probabilmente generare più lavoro per quanto riguarda la sincronizzazione delle loro strutture. E allora? È in gran parte banale, poiché è a malapena più lavoro scrivere due istruzioni ALTER TABLE di una. Inoltre è del tutto possibile che la nuova colonna si applichi solo ai dipendenti effettivi e non abbia alcun significato per prevedere i dipendenti (ad es. EARNED_COMMISSION, LAST_REVIEW_RATING). Alla luce di ciò, avere tabelle separate rende il modello di dati più accurato.
Per quanto riguarda la necessità di duplicare tabelle dipendenti, come sottolinea Ollie, si tratta di un malinteso. Le tabelle che si applicano a tutti i dipendenti indipendentemente dalla loro realtà devono fare riferimento alla tabella EMPLOYEES e non ai suoi figli.
Infine non capisco perché mantenere i dati storici sia più difficile con due tabelle che per una. La maggior parte del codice di journaling dovrebbe essere interamente generata dal dizionario dei dati.
Ce ne sono tre tabelle:
- EMPLOYEES - una tabella principale per garantire EMP_ID univoci
- ACTUAL_EMPLOYEES - una tabella figlio per le persone che lavorano per la tua azienda
- FORECAST_EMPLOYEES - una tabella figlio per le persone che speri di reclutare nella tua azienda
Tieni presente che sto formulando ipotesi sulla tua logica aziendale dagli scarsi dettagli che hai fornito.
Ora mi sembra che le persone che non lavorano ancora per la tua azienda non debbano avere attività associate. In quello scenario avresti una tabella, EMPLOYEE_ACTIVITIES, che è figlia di ACTUAL_EMPLOYEES.
Ma forse hai davvero attività per persone che non esistono. Quindi ecco una scelta:un tavolo o due? Il design di una tabella ha EMPLOYEE_TASKS come figlio della tabella principale EMPLOYEES. Il design a due tabelle ha ACTUAL_EMPLOYEE_TASKS e FORECAST_EMPLOYEE_TASKS rispettivamente come figli delle tabelle ACTUAL_EMPLOYEES e FORECAST_EMPLOYEES.
Quale design è quello corretto dipende dal fatto che sia necessario applicare regole relative all'assegnazione dei compiti. Ad esempio, la tua azienda potrebbe avere una regola che afferma che solo persone reali possono assumere nuovo personale. Quindi sarebbe utile avere un modello che consenta solo di assegnare compiti di reclutamento a ACTUAL_EMPLOYEES.
Ok, ho aggiunto colonne di data alle due tabelle. Ciò ti consentirà di eseguire il rapporto che desideri.