Oracle
 sql >> Base de données >  >> RDS >> Oracle

Comment concevoir un modèle de données qui traite des employés actuels et des employés prévus ?

Je vois plusieurs raisons pour lesquelles vous avez besoin de deux tables pour cela :

  • les vrais employés doivent avoir un nom, un service, etc., tandis que seuls les employés prévisionnels peuvent avoir ces attributs
  • il y aura des responsabilités que seuls de vrais employés peuvent avoir, vous voulez donc pouvoir les référencer séparément

Mais en même temps, vous voulez vous assurer qu'il n'y a pas de conflit d'ID entre les deux tables, car les employés prévus (espérons-le) deviendront des employés réels.

La façon de le faire est d'implémenter une structure de super-type/sous-type. Vous avez donc une table, EMPLOYEES qui garantit des clés primaires uniques, et deux tables dépendantes pour les employés réels et prévus. L'utilisation de la colonne type est cruciale, car elle garantit qu'un employé donné n'apparaît que dans un seul sous-tableau.

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 ;

Les touches peuvent donc sembler un peu étranges. La table parent possède à la fois une clé primaire et une clé unique composée. La clé primaire garantit une instance unique de l'EMP_ID. La clé unique nous permet de créer des clés étrangères sur les tables enfants qui référencent à la fois EMP_ID et EMP_TYPE. Combiné avec les contraintes de vérification sur l'enfant tC'est parce qu'ils font référence à la clé unique sur la table parent plutôt qu'à sa clé primaire. Cet arrangement garantit qu'un employé peut appartenir soit à FORECAST_EMPLOYEES, soit à ACTUAL_EMPLOYEES, mais pas aux deux.

Les clés étrangères sont reportables pour permettre la conversion des employés prévisionnels en employés réels. Cela nécessite trois activités :

  1. supprimer l'enregistrement de FORECAST_EMPLOYEES
  2. insertion d'un enregistrement dans ACTUAL_EMPLOYEES
  3. changer le EMP_TYPE (mais pas l'EMP_ID) dans EMPLOYEES.

La synchronisation des actions 2 et 3 est plus facile avec des contraintes différées.

Notez également que les autres contraintes de clé étrangère faisant référence à EMPLOYEES doivent utiliser la clé primaire plutôt que la clé unique. Si la relation se soucie du type d'employé, elle devrait probablement être liée aux tables enfants à la place.

Bienvenue dans le monde de la modélisation des données. C'est un gros mal de tête. Parce qu'il est difficile d'essayer d'intégrer la réalité désordonnée dans un modèle de données propre  :vous avez besoin d'exigences claires pour bien faire les choses et d'une compréhension de ce qui compte le plus pour pouvoir faire des compromis judicieux.

J'ai proposé une approche super-type/sous-type sur la base de votre autre question, et parce que cela semble être la meilleure façon de traiter deux ensembles de données :les employés réels et les employés fictifs. Je pense que ces deux groupes doivent être traités différemment. Par exemple, j'insisterais pour que les managers soient de vrais employés. C'est facile à faire avec une contrainte d'intégrité contre ACTUAL_EMPLOYEES et beaucoup plus difficile à réaliser avec une seule table qui contient les deux types d'employés.

Bien sûr, avoir deux tables signifie peut-être générer plus de travail en ce qui concerne la synchronisation de leurs structures. Et alors? C'est en grande partie trivial, car il est à peine plus difficile d'écrire deux instructions ALTER TABLE qu'une seule. De plus, il est tout à fait possible que la nouvelle colonne ne s'applique qu'aux employés réels et n'ait aucune signification pour les employés prévus (par exemple, EARNED_COMMISSION, LAST_REVIEW_RATING). Dans cette optique, le fait d'avoir des tables séparées rend le modèle de données plus précis.

En ce qui concerne la nécessité de dupliquer des tables dépendantes, comme le souligne Ollie, c'est un malentendu. Les tables qui s'appliquent à tous les employés, quelle que soit leur actualité, doivent faire référence à la table EMPLOYEES et non à ses enfants.

Enfin, je ne comprends pas pourquoi la maintenance des données historiques est plus difficile avec deux tables qu'avec une. La plupart des codes de journalisation doivent être entièrement générés à partir du dictionnaire de données.

Il y a trois tableaux :

  • EMPLOYEES :une table principale pour garantir des EMP_ID uniques
  • ACTUAL_EMPLOYEES - une table enfant pour les personnes qui travaillent pour votre entreprise
  • FORECAST_EMPLOYEES - une table enfant pour les personnes que vous espérez recruter dans votre entreprise

Veuillez garder à l'esprit que je fais des hypothèses sur votre logique métier à partir des rares détails que vous avez fournis.

Maintenant, il me semble que les personnes qui ne travaillent pas encore pour votre entreprise ne devraient pas avoir d'activités associées. Dans ce scénario, vous auriez une table, EMPLOYEE_ACTIVITIES, qui est un enfant de ACTUAL_EMPLOYEES.

Mais peut-être avez-vous vraiment des activités pour des gens qui n'existent pas. Alors au choix :une table ou deux ? La conception à table unique a EMPLOYEE_TASKS comme enfant de la table principale EMPLOYEES. La conception à deux tables a ACTUAL_EMPLOYEE_TASKS et FORECAST_EMPLOYEE_TASKS comme enfants des tables ACTUAL_EMPLOYEES et FORECAST_EMPLOYEES respectivement.

Quelle conception est la bonne dépend si vous devez appliquer des règles concernant l'attribution des tâches. Par exemple, votre entreprise peut avoir une règle qui stipule que seules de vraies personnes peuvent embaucher de nouveaux employés. Il serait donc utile de disposer d'un modèle permettant uniquement d'attribuer des tâches de recrutement à ACTUAL_EMPLOYEES.

D'accord, j'ai ajouté des colonnes de date aux deux tables. Cela vous permettra d'exécuter le rapport que vous souhaitez.