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.
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.
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.
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:
- Insertar
el empleado.
- Obtener su identificador y fecha de
contratación.
- Consultar
las deducciones obligatorias.
- Crear la relación en EmpXTipoDed.
- Obtener el identificador de la
relación.
- Insertar la información específica en
la subtabla correspondiente.
- 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
Publicar un comentario