ProgramaciónDesarrollador SQL

Describe las características, ventajas y desventajas del procesamiento de datos en serie utilizando cursores (CURSOR) en SQL. ¿Cuándo es razonable usar cursores y cuándo se deben evitar en favor de operaciones basadas en conjuntos (set-based)? Proporcione un ejemplo de uso de un cursor.

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

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:

  • Permiten implementar procedimientos complejos donde cada fila requiere un tratamiento separado o verificación de condiciones externas.
  • Convenientes para la integración con sistemas legados o migraciones donde se necesita control paso a paso.

Desventajas y obstáculos:

  • Los cursores son generalmente MUY lentos: el procesamiento se realiza uno a uno, no de forma basada en conjuntos;
  • Ocupan muchos recursos y pueden bloquear tablas;
  • No son escalables para grandes volúmenes de datos;
  • Es mejor reescribir en SQL basado en conjuntos o usar procesamiento por lotes.

Pregunta capciosa.

¿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.