Creación del Trigger

Hora de inicio: 8:00 a.m. 

Hora de finalización: 11:30 a.m.

Horas trabajadas: 3 h 30 min


Objetivo de la sesión

El objetivo principal de esta sesión fue implementar el trigger encargado de asociar automáticamente las deducciones obligatorias a cada empleado nuevo que se inserte en la base de datos.

De acuerdo con el enunciado del proyecto, cuando un empleado es registrado en el sistema, este debe quedar asociado desde ese momento con todas las deducciones marcadas como obligatorias dentro del catálogo de tipos de deducción. Actualmente, la única deducción obligatoria definida es la deducción de ley correspondiente a la CCSS, sin embargo, decidí realizar el trigger de una manera más general, por si en el catálogo despies se agregaban otros.

Actividades realizadas

8:00 a.m. – 8:40 a.m.

Análisis del requerimiento y de las tablas relacionadas

Durante la primera parte de la sesión revisé el requerimiento del proyecto relacionado con la inserción de empleados y la asignación automática de deducciones obligatorias, ya que no entendía muy bien.

El requerimiento indica que esta asociación debe realizarse por medio de un trigger, por lo que la operación no debe depender de que la capa lógica recuerde ejecutar un segundo procedimiento después de insertar al empleado. La ventaja de manejarlo directamente desde la base de datos es que la regla se cumple independientemente del origen de la inserción, ya sea desde el sitio web o desde la simulación.


Después de revisar el requerimiento, analicé las tablas que participan en el proceso.

La tabla Empleado es la tabla sobre la cual se ejecuta el trigger. Al insertarse un nuevo registro, se necesita consultar el catálogo TipoDeduccion para obtener todas las deducciones cuyo atributo FlagObligatorio sea igual a 1.

Posteriormente, cada una de esas deducciones debe asociarse con el empleado mediante la tabla EmpXTipoDed. Esta tabla funciona como la asociación principal entre un empleado y un tipo de deducción.

Además, según la naturaleza de la deducción, también se debe insertar un registro en una de las siguientes subtablas:

  • EXTDPorcentual, cuando la deducción se calcula mediante un porcentaje.
  • EXTDMontoFijo, cuando la deducción corresponde a un monto fijo.

Este análisis fue importante porque la operación no consistía únicamente en insertar una fila en una tabla, sino en mantener correctamente la relación entre la asociación general y su información específica.

8:40 a.m. – 9:20 a.m.

Creación de la estructura general del trigger

Después de tener claro el flujo de datos, comencé a construir el trigger con el nombre:

trg_AsignarDeduccionesObligatorias

El trigger se definió sobre la tabla dbo.Empleado y se configuró como AFTER INSERT. Esto significa que se ejecuta después de quese intenta insertar el empleado, pero formando parte de la misma transacción.

Lo anterior es importante porque, si ocurre un error mientras se asignan las deducciones, también puede revertirse la inserción del empleado. De esta forma no queda un empleado parcialmente registrado, es decir, insertado en la tabla principal pero sin las asociaciones obligatorias que necesita para el procesamiento de planilla.

    Img. 2: Definición del trigger como AFTER INSERT y uso de SET NOCOUNT ON.

Luego declaré las variables necesarias para controlar el procesamiento.

También creé una tabla variable llamada @deduccionesObligatorias. La función de esta tabla es almacenar temporalmente todas las deducciones obligatorias encontradas en el catálogo antes de comenzar a insertarlas para el nuevo empleado.

La tabla incluye una columna RowNum de tipo IDENTITY, que permite numerar los registros y recorrerlos posteriormente mediante un ciclo.

    Img. 3: Variables de control y tabla variable utilizada para almacenar las deducciones        obligatorias.

Decidí manejarlo de esta manera para no asumir que siempre existirá una única deducción obligatoria. Aunque en los datos actuales solamente se encuentra la deducción de ley, el trigger queda preparado para que en el futuro se puedan agregar nuevas deducciones obligatorias sin modificar su lógica principal.

9:20 a.m. – 10:05 a.m.

Obtención del empleado y de las deducciones obligatorias

Una de las partes principales fue obtener la información del empleado que acaba de ser insertado.

Para esto utilicé la tabla virtual INSERTED. SQL Sgenera esta tabla automáticamente durante la ejecución de un trigger de inserción y coloca en ella los datos de los registros recién insertados.

Desde INSERTED obtuve:

  • El identificador del nuevo empleado.
  • Su fecha de contratación.

La fecha de contratación se utiliza como fecha inicial de las deducciones obligatorias. Consideré que esta era la opción más coherente, ya que una deducción obligatoria debe comenzar a estar vigente desde el momento en que el empleado inicia su relación laboral.

Después de obtener estos datos, consulté la tabla TipoDeduccion y cargué en la tabla variable únicamente las deducciones que cumplen con la condición de que FlagObligatorio = 1

De cada deducción almacené su identificador, el indicador que determina si es porcentual y su valor.

   Img. 4: Lectura del empleado desde INSERTED y carga de las deducciones obligatorias desde el  catálogo.

Una vez terminada la consulta, utilicé @@ROWCOUNT para conocer cuántas deducciones obligatorias fueron encontradas. Esta cantidad se almacenó en @totalRows y se utilizó como límite para el ciclo encargado de procesarlas.

10:05 a.m. – 10:50 a.m.

Inserción de las asociaciones y manejo de los subtipos

Para recorrer las deducciones obligatorias utilicé un ciclo WHILE. En cada iteración se consulta una fila de la tabla variable y se cargan sus valores en las variables de control.

Posteriormente se crea la asociación principal en EmpXTipoDed, almacenando:

  • El identificador del empleado.
  • El identificador del tipo de deducción.
  • La fecha de contratación como fecha inicial.
  • NULL como fecha final.
  • La fecha y hora en que se genera el registro.
  • El usuario y la IP correspondientes al sistema.

La fecha final se deja en NULL porque la deducción obligatoria debe quedar vigente de forma indefinida. Solamente tendría una fecha final si en algún momento se desactivara o finalizara explícitamente la asociación.

Para los campos de auditoría utilicé PostByUser = 0 y PostInIP = '0.0.0.0'. Esto representa que el registro fue generado automáticamente por el sistema y no directamente por un usuario autenticado desde una dirección IP determinada.

    Img. 5: Inserción de la asociación entre el empleado y la deducción en EmpXTipoDed.

Después de insertar la asociación fue necesario obtener el identificador generado automáticamente en EmpXTipoDed. Para esto utilicé SCOPE_IDENTITY().

Este valor es importante porque las tablas EXTDPorcentual y EXTDMontoFijo utilizan el mismo identificador de la asociación principal. De esta manera se mantiene correctamente la relación entre el registro general y sus datos específicos.

Luego agregué una condición basada en el atributo EsPorcentual.

Si el valor es igual a 1, se inserta el identificador de la asociación y el porcentaje en EXTDPorcentual.

En caso contrario, el registro se inserta en EXTDMontoFijo, utilizando el valor como monto de la deducción.

    Img. 6: Uso de SCOPE_IDENTITY y selección de la subtabla según el tipo de deducción.

Esta parte fue una de las más importantes del trigger, ya que no bastaba con conocer que la deducción era obligatoria. También era necesario respetar el diseño de la base de datos y colocar su valor en la tabla correspondiente.

10:50 a.m. – 11:30 a.m.

Manejo de errores y revisión final

Durante la última parte de la sesión agregué el manejo de errores mediante bloques TRY y CATCH.

Finalmente revisé el flujo completo del trigger, verificando que la operación siguiera el siguiente orden:

  1. Insertar el empleado.
  2. Obtener su identificador y fecha de contratación.
  3. Consultar las deducciones obligatorias.
  4. Crear la relación en EmpXTipoDed.
  5. Obtener el identificador de la relación.
  6. Insertar la información específica en la subtabla correspondiente.
  7. Repetir el proceso por cada deducción obligatoria encontrada.


Buenas prácticas aplicadas y aprendizajes

  • Las reglas que siempre deben cumplirse al insertar un registro pueden implementarse en la base de datos mediante triggers, evitando depender completamente de la capa lógica.
  • No se debe asumir que un catálogo siempre tendrá la misma cantidad de registros. Consultar las deducciones mediante FlagObligatorio hace que la solución sea más mantenible que utilizar directamente el identificador de la deducción de ley.
  • La tabla virtual INSERTED permite acceder a los datos que provocaron la ejecución de un trigger.
  • Cuando una inserción principal genera un identificador necesario para otras tablas relacionadas, SCOPE_IDENTITY() permite obtener el identificador generado dentro del mismo ámbito.
  • Cuando una entidad utiliza tablas de subtipo, primero debe crearse el registro principal y después utilizar su identificador para insertar la información específica.
  • Un trigger forma parte de la transacción que lo activa. Por esta razón, un error dentro del trigger puede afectar y revertir la operación original.
  • Es recomendable utilizar TRY-CATCH y una tabla de errores para facilitar la identificación de problemas durante las pruebas y la simulación.
  • Los registros creados automáticamente por la base de datos deben diferenciarse de los generados directamente por un usuario. En este caso se utilizaron valores reservados para representar al sistema en los campos de auditoría.

 

Material utilizado

  • Enunciado del proyecto de Control de Asistencia y Planilla Obrera.
  • Diseño físico de la base de datos.
  • Catálogo de tipos de deducción.
  • Tablas Empleado, TipoDeduccion, EmpXTipoDed, EXTDPorcentual, EXTDMontoFijo y DBError.
  • Documentación y conocimientos sobre triggers DML, la tabla virtual INSERTED, SCOPE_IDENTITY(), transacciones y manejo de errores en SQL Server.
  • ¿Qué diablos es un Trigger? | ejemplo sencillo en Sql Server https://youtu.be/uTx7xd4ojkk?si=Fc-dBAuU9oJV0I9B

 


Comentarios

Entradas más populares de este blog

Creación del repositorio y estructura básica del proyecto