triggers-creacion-uso-sql

Triggers en SQL Server

  • 5 min

Un Trigger es un tipo especial de procedimiento almacenado que no se ejecuta manualmente. Se dispara automáticamente cuando ocurre un evento específico en una tabla.

Es como un sistema de alarma o un sensor de movimiento: tú no lo enciendes cada vez; simplemente configuras “Si alguien abre esta puerta, que suene la sirena”.

En SQL, la regla sería: “Si alguien borra un cliente, guárdalo en la tabla de históricos”

En T-SQL, existen dos tipos principales de Triggers:

  1. Triggers AFTER: Se ejecutan después que ocurra el evento, y los cambios ya se han aplicado a la tabla.
  2. Triggers INSTEAD OF: Se ejecutan en lugar del evento, lo que significa que el evento original no se lleva a cabo (a menos que el Trigger lo permita explícitamente).

Tipos de Eventos

Un Trigger se ejecuta automáticamente cuando ocurre un evento específico en una tabla. Estos eventos pueden ser INSERT, DELETE y UPDATE.

Dentro de un trigger, SQL Server crea dos tablas temporales en memoria que contienen los datos afectados por la operación:

  1. inserted: Contiene las filas nuevas (en un INSERT) o las versiones nuevas de las filas (en un UPDATE).
  2. deleted: Contiene las filas eliminadas (en un DELETE) o las versiones antiguas de las filas (en un UPDATE).

En función del tipo de evento, tendrás datos en una, otra, o ambas de estas tablas.

OperaciónTabla insertedTabla deleted
INSERTLas nuevas filas(Vacía)
DELETE(Vacía)Las filas borradas
UPDATELas filas con los nuevos valoresLas filas con los viejos valores

Triggers de tipo AFTER

Son los más comunes. Se ejecutan después de que la acción haya tenido éxito (INSERT, UPDATE, DELETE), pero antes de confirmar la transacción.

Por ejemplo, imaga que queremos que, si alguien cambia el precio de un producto, se guarde automáticamente un registro de “quién, cuándo y cuánto”.

-- 1. La tabla donde guardaremos el historial
CREATE TABLE HistorialPrecios (
    ProductoID INT,
    PrecioAntiguo DECIMAL(10,2),
    PrecioNuevo DECIMAL(10,2),
    Usuario VARCHAR(50),
    FechaCambio DATETIME DEFAULT GETDATE()
);
GO

-- 2. El Trigger
CREATE TRIGGER trg_AuditoriaPrecios
ON Productos
AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;

    -- Detectamos si la columna Precio fue tocada
    IF UPDATE(Precio)
    BEGIN
        -- Insertamos en el historial cruzando las tablas mágicas
        INSERT INTO HistorialPrecios (ProductoID, PrecioAntiguo, PrecioNuevo, Usuario)
        SELECT 
            i.ProductoID, 
            d.Precio,  -- Valor viejo (viene de DELETED)
            i.Precio,  -- Valor nuevo (viene de INSERTED)
            SYSTEM_USER -- Usuario actual
        FROM inserted i
        INNER JOIN deleted d ON i.ProductoID = d.ProductoID;
    END
END
Copied!

Ahora, cada vez que hagas un UPDATE Productos SET Precio = ..., el trigger saltará silenciosamente y guardará la evidencia.

¡Cuidado con el pensamiento “Fila a Fila”! El trigger no se dispara una vez por fila, se dispara una vez por instrucción.

Si haces un UPDATE masivo de 1.000 productos, el trigger corre una sola vez, y la tabla inserted tendrá 1.000 filas.

Por eso en el ejemplo anterior usamos un INSERT ... SELECT basado en conjuntos, y no variables escalares.

Trigger de tipo INSTEAD OF

Estos son triggers (interceptores) cancelan la acción original y ejecutan su propio código en su lugar. Son muy útiles para proteger datos o manejar Vistas complejas.

Por ejemplo, el caso del “Soft Delete” (Borrado lógico). En muchas empresas está prohibido borrar datos (DELETE). En su lugar, se marca una columna Activo = 0.

Podemos forzar esto con un trigger, incluso si el programador intenta hacer un DELETE.

CREATE TRIGGER trg_ProtegerClientes
ON Clientes
INSTEAD OF DELETE
AS
BEGIN
    SET NOCOUNT ON;

    -- En lugar de borrar, actualizamos el campo Activo
    UPDATE Clientes
    SET Activo = 0
    WHERE ClienteID IN (SELECT ClienteID FROM deleted);
    
    PRINT 'El registro no se borró, se ha marcado como inactivo.';
END
Copied!

Si ejecutas DELETE FROM Clientes WHERE ID = 1, el registro seguirá ahí, pero marcado como inactivo.

El Lado Oscuro de los Triggers

Los triggers son muy potentes, pero tienen mala fama entre los DBAs. ¿Por qué?

  1. Son invisibles: Un desarrollador nuevo llega, hace un INSERT, y de repente le da un error o tarda mucho. No sabe por qué, porque el trigger está oculto.
  2. Matan el rendimiento: El trigger forma parte de la transacción. Si el trigger tarda 5 segundos, tu INSERT se comerá los 5 segundos. Mantienen bloqueos en las tablas más tiempo.
  3. Recursividad: Un trigger A actualiza la tabla B, que tiene un trigger que actualiza la tabla A… Puedes crear bucles infinitos (SQL Server los detiene tras 32 niveles, pero el error saltará igual).

Buenas Prácticas

  1. Mantenlos cortos: Lógica mínima y rapidísima.
  2. No devuelvas resultados: Nunca pongas un SELECT * FROM ... dentro de un trigger, o romperás la aplicación que espera solo un mensaje de “filas afectadas”.
  3. Documenta: Si usas triggers, documentalo claramente para que el equipo sepa que existen.