sql >> Base de Datos >  >> RDS >> Oracle

¿Cómo diseñar un modelo de datos que trate con los empleados actuales y los empleados previstos?

Puedo ver un par de razones por las que necesita dos tablas para esto:

  • los empleados reales deben tener un nombre, un departamento, etc., mientras que los empleados previstos solo pueden tener estos atributos
  • habrá responsabilidades que solo los empleados reales pueden tener, por lo que querrá poder hacer referencia a ellos por separado

Pero al mismo tiempo, desea asegurarse de que no haya conflicto de ID en las dos tablas, porque (con suerte) los empleados previstos se convertirán en empleados reales.

La forma de hacerlo es implementar una estructura de supertipo/subtipo. Por lo tanto, tiene una tabla, EMPLEADOS, que garantiza claves primarias únicas, y dos tablas dependientes para empleados reales y previstos. El uso de la columna de tipo es fundamental, ya que garantiza que un determinado empleado solo aparezca en una subtabla.

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 ;

Así que las teclas pueden verse un poco extrañas. La tabla principal tiene una clave principal y una clave única compuesta. La clave principal garantiza una sola instancia de EMP_ID. La clave única nos permite crear claves externas en las tablas secundarias que hacen referencia tanto a EMP_ID como a EMP_TYPE. Combinado con las restricciones de verificación en el elemento secundario, esto se debe a que hacen referencia a la clave única en la tabla principal en lugar de a su clave principal. Este acuerdo garantiza que un empleado pueda estar en FORECAST_EMPLOYEES o ACTUAL_EMPLOYEES, pero no en ambos.

Las claves foráneas son diferibles para permitir la conversión de empleados previstos en empleados reales. Esto requiere tres actividades:

  1. borrando el registro de FORECAST_EMPLOYEES
  2. insertar un registro en ACTUAL_EMPLOYEES
  3. cambiar el EMP_TYPE (pero no EMP_ID) en EMPLEADOS.

Sincronizar las acciones 2 y 3 es más fácil con restricciones diferidas.

Además, tenga en cuenta que otras restricciones de clave externa que hacen referencia a EMPLEADOS deben usar la clave principal en lugar de la clave única. Si la relación se preocupa por el tipo de empleado, probablemente debería vincularse a las tablas secundarias.

Bienvenido al mundo del modelado de datos. Es un gran dolor de cabeza. Porque tratar de encajar la realidad desordenada en un modelo de datos limpio es difícil :necesita requisitos claros para hacerlo bien, y una comprensión de lo que más importa para que pueda hacer concesiones sensatas.

Propuse un enfoque de supertipo/subtipo sobre la base de su otra pregunta, y porque parece ser la mejor manera de manejar dos conjuntos de datos:empleados reales y empleados ficticios. Creo que esos dos grupos deben ser tratados de manera diferente. Por ejemplo, insistiría en que los gerentes sean empleados reales. Esto es fácil de hacer con una restricción de integridad contra ACTUAL_EMPLOYEES y mucho más difícil de lograr con una sola tabla que contiene ambos tipos de empleados.

Seguro que tener dos tablas significa posiblemente generar más trabajo con respecto a la sincronización de sus estructuras. ¿Y qué? Es en gran medida trivial, ya que apenas es más trabajo escribir dos sentencias ALTER TABLE que una. Además, es muy posible que la nueva columna se aplique solo a los empleados reales y no tenga significado para los empleados previstos (p. ej., GANADO_COMISIÓN, ÚLTIMA_REVISIÓN_CALIFICACIÓN). En ese sentido, tener tablas separadas hace que el modelo de datos sea más preciso.

Con respecto a tener que duplicar tablas dependientes, como señala Ollie, eso es un malentendido. Las tablas que se aplican a todos los empleados, independientemente de su actualidad, deben hacer referencia a la tabla EMPLEADOS, no a sus elementos secundarios.

Finalmente, no entiendo por qué mantener datos históricos es más difícil con dos tablas que con una. La mayoría del código de diario debe generarse completamente a partir del diccionario de datos.

Hay tres tablas:

  • EMPLEADOS:una tabla maestra para garantizar EMP_ID únicos
  • ACTUAL_EMPLOYEES:una tabla secundaria para las personas que trabajan para su empresa
  • FORECAST_EMPLOYEES:una tabla secundaria para las personas que espera contratar para su empresa

Tenga en cuenta que estoy haciendo suposiciones sobre su lógica comercial a partir de los escasos detalles que ha proporcionado.

Ahora me parece que las personas que aún no trabajan para su empresa no deberían tener ninguna actividad asociada. En ese escenario, tendría una tabla, EMPLOYEE_ACTIVITIES, que es secundaria de ACTUAL_EMPLOYEES.

Pero tal vez realmente tengas actividades para personas que no existen. Así que aquí hay una opción:¿una mesa o dos? El diseño de una tabla tiene EMPLOYEE_TASKS como elemento secundario de la tabla maestra EMPLOYEES. El diseño de dos tablas tiene ACTUAL_EMPLOYEE_TASKS y FORECAST_EMPLOYEE_TASKS como elementos secundarios de las tablas ACTUAL_EMPLOYEES y FORECAST_EMPLOYEES respectivamente.

Qué diseño es el correcto depende de si necesita hacer cumplir las reglas con respecto a la asignación de tareas. Por ejemplo, su empresa podría tener una regla que establezca que solo las personas reales pueden contratar personal nuevo. Por lo tanto, sería útil tener un modelo que solo permita asignar tareas de reclutamiento a ACTUAL_EMPLOYEES.

Bien, he agregado columnas de fecha a las dos tablas. Eso le permitirá ejecutar el informe que desee.