Creación de desencadenadores
Los desencadenadores son procedimientos almacenados especiales que se ejecutan automáticamente cuando se producen eventos específicos en la base de datos. Los desencadenadores se definen para mantener la integridad de los datos, aplicar reglas de negocio y automatizar las operaciones de base de datos sin necesidad de código de nivel de aplicación.
Descripción de los aspectos básicos del desencadenador
Un desencadenador responde a cambios de esquema o modificación de datos en la base de datos. Al crear un desencadenador, se especifica el evento que lo activa y las acciones que realiza.
Los desencadenadores se ejecutan automáticamente. A diferencia de los procedimientos almacenados a los que se llama explícitamente, los desencadenadores se activan en respuesta a INSERT, UPDATE, DELETE o instrucciones DDL. Esta ejecución automática hace que sean eficaces para aplicar reglas que deben aplicarse de forma coherente en todas las modificaciones de datos.
SQL Server admite dos categorías principales de desencadenadores: desencadenadores DML (lenguaje de manipulación de datos) y desencadenadores DDL (lenguaje de definición de datos). Los desencadenadores DML responden a los cambios en los datos de tabla, mientras que los desencadenadores DDL responden a cambios de esquema, como las instrucciones CREATE, ALTER o DROP.
Creación de desencadenadores DML para modificaciones de datos
Los desencadenadores DML supervisan y responden a los cambios de datos en tablas o vistas. Puede definirlos como desencadenadores tipo AFTER o tipo INSTEAD OF.
Los desencadenadores AFTER se ejecutan después de que se complete la instrucción de desencadenamiento. La base de datos realiza primero la modificación de datos y, a continuación, ejecuta el código de desencadenador. Use desencadenadores AFTER para validar cambios, actualizar tablas relacionadas o registrar modificaciones.
CREATE TRIGGER tr_UpdateInventory
ON Sales.OrderDetails
AFTER INSERT
AS
BEGIN
UPDATE Inventory.Products
SET QuantityInStock = QuantityInStock - i.Quantity
FROM Inventory.Products p
INNER JOIN inserted i ON p.ProductID = i.ProductID;
END;
LOS desencadenadores INSTEAD OF reemplazan la instrucción de modificación de datos original. El código de desencadenador se ejecuta en lugar de la operación INSERT, UPDATE o DELETE. Utilice desencadenadores INSTEAD OF para modificar vistas que normalmente no aceptarían modificaciones directas o para implementar lógica de negocios compleja:
CREATE TRIGGER tr_UpdateOrderView
ON Sales.OrderSummaryView
INSTEAD OF UPDATE
AS
BEGIN
UPDATE Sales.Orders
SET OrderStatus = i.OrderStatus,
ModifiedDate = GETDATE()
FROM Sales.Orders o
INNER JOIN inserted i ON o.OrderID = i.OrderID;
END;
Con los desencadenadores DML, puede acceder a las pseudo-tablas inserted y deleted. Estas tablas temporales almacenan copias de las filas afectadas.
INSERT las operaciones rellenan la tabla inserted, DELETE las operaciones rellenan la tabla deleted y UPDATE las operaciones rellenan ambas tablas con valores antiguos en deleted y nuevos en inserted.
Implementación de desencadenadores para eventos específicos
Especifique qué eventos de modificación de datos activan el desencadenador. Un único desencadenador puede responder a varios eventos combinando INSERT, UPDATEy DELETE en la definición del desencadenador.
Para un control preciso, se crean desencadenadores independientes para cada operación. Este enfoque simplifica el código y facilita el mantenimiento de los desencadenadores:
CREATE TRIGGER tr_LogPriceChanges
ON Products.Catalog
AFTER UPDATE
AS
BEGIN
IF UPDATE(Price)
BEGIN
INSERT INTO Audit.PriceHistory (ProductID, OldPrice, NewPrice, ChangeDate)
SELECT d.ProductID, d.Price, i.Price, GETDATE()
FROM deleted d
INNER JOIN inserted i ON d.ProductID = i.ProductID
WHERE d.Price <> i.Price;
END;
END;
Al mismo tiempo, puede combinar eventos cuando la misma lógica se aplica a varias operaciones. Por ejemplo, podría crear un único desencadenador de auditoría que responda a INSERT, UPDATEy DELETE:
CREATE TRIGGER tr_AuditEmployeeChanges
ON HR.Employees
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
DECLARE @Operation NVARCHAR(10);
IF EXISTS (SELECT * FROM inserted) AND NOT EXISTS (SELECT * FROM deleted)
SET @Operation = 'INSERT';
ELSE IF EXISTS (SELECT * FROM inserted) AND EXISTS (SELECT * FROM deleted)
SET @Operation = 'UPDATE';
ELSE
SET @Operation = 'DELETE';
INSERT INTO Audit.EmployeeLog (EmployeeID, Operation, ChangeDate)
SELECT COALESCE(i.EmployeeID, d.EmployeeID), @Operation, GETDATE()
FROM inserted i
FULL OUTER JOIN deleted d ON i.EmployeeID = d.EmployeeID;
END;
La UPDATE() función le ayuda a determinar qué columnas han cambiado. Compruebe columnas específicas para evitar el procesamiento innecesario cuando solo determinados campos sean importantes para la lógica de negocios.
Aplicación de procedimientos recomendados de desencadenador
Los desencadenadores afectan al rendimiento de la base de datos porque se ejecutan con todas las operaciones aptas. Puede escribir código de desencadenador eficaz para minimizar el impacto en el rendimiento de las transacciones.
Mantenga la lógica del disparador centrada y mínima. Realice solo operaciones esenciales en el cuerpo del desencadenador. Para operaciones complejas o lentas, considere la posibilidad de registrar los detalles del evento y procesarlos de forma asincrónica a través de un trabajo independiente:
CREATE TRIGGER tr_QueueLargeOrders
ON Sales.Orders
AFTER INSERT
AS
BEGIN
INSERT INTO Processing.OrderQueue (OrderID, TotalAmount, QueuedDate)
SELECT OrderID, TotalAmount, GETDATE()
FROM inserted
WHERE TotalAmount > 10000;
END;
Evite las operaciones recursivas en las que una modificación del desencadenador hace que el mismo desencadenador se active de nuevo. Establezca la RECURSIVE_TRIGGERS opción de base de datos de forma adecuada y diseñe los desencadenadores para evitar bucles infinitos.
Gestione los errores correctamente dentro de los desencadenadores. El comportamiento de la transacción depende del control de errores. Si un desencadenador encuentra un error y no lo gestionas, SQL Server revierte tanto el desencadenador como la instrucción original.
CREATE TRIGGER tr_ValidateOrderDate
ON Sales.Orders
AFTER INSERT, UPDATE
AS
BEGIN
IF EXISTS (SELECT * FROM inserted WHERE OrderDate > GETDATE())
BEGIN
THROW 50001, 'Order date cannot be in the future', 1;
END;
END;
Documente los desencadenadores exhaustivamente. Otros desarrolladores deben comprender por qué existen desencadenadores y qué hacen, ya que se ejecutan de forma invisible durante las operaciones normales de la base de datos.
Ahora que comprende cómo crear e implementar desencadenadores, está listo para explorar cómo se integran con otros objetos de programación para crear soluciones completas de base de datos.