Los cursores en SQL permiten recorrer conjuntos de datos fila por fila y realizar acciones específicas en cada registro, lo que se parece a la iteración en programación. Esto es conveniente para lógicas complejas paso a paso que no son posibles mediante un solo query SQL (por ejemplo, cálculos secuenciales con cambios en el estado externo).
Ejemplo de cursor:
DECLARE my_cursor CURSOR FOR SELECT id, balance FROM Accounts WHERE isActive = 1; OPEN my_cursor; DECLARE @id INT, @bal DECIMAL(10,2); FETCH NEXT FROM my_cursor INTO @id, @bal; WHILE @@FETCH_STATUS = 0 BEGIN UPDATE Accounts SET balance = @bal * 1.05 WHERE id = @id; FETCH NEXT FROM my_cursor INTO @id, @bal; END CLOSE my_cursor; DEALLOCATE my_cursor;
Ventajas:
Desventajas y obstáculos:
¿Se puede usar un cursor dentro de un trigger? ¿Cuáles pueden ser las consecuencias para el rendimiento de la base de datos?
Respuesta y ejemplo: El uso de un cursor dentro de un trigger es posible, pero no se recomienda en absoluto — cada operación DML puede ejecutar el cursor para cada fila afectada, lo que conduce a un crecimiento avalancha de consultas y bloqueos.
CREATE TRIGGER UpdateBalance ON Accounts AFTER INSERT AS DECLARE c CURSOR FOR SELECT id FROM inserted; -- ¡malo! OPEN c; -- ...
Historia
Proyecto: Resumen de pedidos en retail. Se planteó la tarea de contar los inventarios si se encontraba un defecto en el lote — los lotes posteriores requieren recuento manual a través de descuentos actualizados. Se utilizó un cursor para recorrer los lotes. Posteriormente se descubrió que al ejecutarse múltiples veces el hilo se bloqueaba durante horas, la carga del servidor aumentaba exponencialmente y la contención de bloqueos provocaba fallos.
Historia
Proyecto: ERP, migración de datos. En el procedimiento de importación se agregó el manejo de errores mediante un cursor. No se tuvo en cuenta que en 5 millones de filas, el cursor funcionaba 40 veces más lento que un procesamiento por lotes utilizando UPDATE + CASE basado en conjuntos. Debido a la migración lenta, las fechas límite se retrasaron.
Historia
Proyecto: Facturación de empresa financiera. Se agregó un cursor al trigger de actualización de la tabla de movimientos de fondos para calcular el nuevo saldo agregado. En producción, esto llevó a un "STOP THE WORLD" — la inserción incluso de un solo registro ralentizó el funcionamiento del servicio debido a la ejecución del cursor anidado para múltiples filas.