Cuando he trabajado con procedimientos almacenados en SQL Server, comúnmente me surgía la necesidad de iterar registros y lo hacia con tablas temporales y cursores.

A groso modo lo que tenia que hacer era lo siguiente:

  1. Crear una tabla temporal (#Temp)
  2. Insertar los datos a procesar
  3. Declarar un cursor
  4. Recorrer los registros uno por uno
  5. Cerrar y liberar el cursor
  6. Eliminar la tabla temporal

Por lo general este método no presentaba problemas pero sí me llegó a pasar que en algún procedimiento tenia que aplicar lógica de negocio durante el iterado de los datos y esto me generaba problemas porque no podía terminar la ejecución sin eliminar la tabla temporal ni cerrar el cursor y esto representaba un inconveniente por lo siguiente:

  • Es fácil olvidar eliminar la tabla temporal
  • Existe el riesgo de dejar cursores abiertos
  • El código se vuelve más complejo y difícil de mantener
  • Puede afectar el rendimiento si no se maneja correctamente

Buscando alternativas más limpias, encontré una forma mucho más sencilla y controlada de hacerlo.

Una alternativa más simple: variables tipo tabla + WHILE

En lugar de usar tablas temporales y cursores, podemos utilizar una variable de tipo tabla junto con una columna IDENTITY para simular un índice, y recorrer los registros usando un ciclo WHILE.

Ejemplo

Supongamos que queremos iterar los miembros de un grupo de personas,

SQL
DECLARE @grupoId INT = 28
	, @idxMiembro INT = 0 -- El indice debe comenzar en 0
	, @NumMiembros INT = 0

DECLARE @miembrosDeGrupo TABLE (
	idx INT NOT NULL IDENTITY,
	clienteId BIGINT NOT NULL,
	nombreCliente VARCHAR(500) NOT NULL
)

-- Se obtienen los datos a iterar
INSERT INTO @miembrosDeGrupo
SELECT cl.clienteId, cl.nombreCompleto
FROM MiembrosGrupos mg
INNER JOIN clientes cl
ON mg.clienteId = cl.clienteId
WHERE grupoId = @grupoId

-- Se obtiene el numero de datos a iterar
SELECT @NumMiembros = COUNT(*)
FROM @miembrosDeGrupo

WHILE @idxMiembro <= @NumMiembros
BEGIN
	-- Obtenemos los elementos por indice
	SELECT * FROM @miembrosDeGrupo WHERE idx = @idxMiembro

	-- No olvidar incrementar el indice
	SET @idxMiembro += 1
END

¿Por qué este enfoque es mejor?

Este método tiene varias ventajas importantes:

1. No necesitas limpiar nada

Las variables de tipo tabla viven únicamente dentro del scope del procedimiento y no tienes que preocuparte por eliminarlas.

2. Evitas cursores

Los cursores son poderosos, pero también propensos a errores y problemas de rendimiento si no se usan correctamente.

3. Código más limpio y fácil de mantener

El uso de WHILE con un índice hace que la lógica sea más clara y controlada.

4. Menor riesgo de errores

No hay cursores abiertos ni recursos pendientes por liberar.

Consideraciones importantes

Aunque este enfoque es muy útil, hay algunos puntos que debes tener en cuenta:

  • Asegúrate de inicializar correctamente el índice (@idxMiembro)
  • Controla bien el límite del ciclo (@NumMiembros)
  • Este patrón es ideal para conjuntos de datos pequeños o medianos

⚠️ Para grandes volúmenes de datos, siempre vale la pena evaluar si puedes resolver el problema con operaciones basadas en conjuntos (set-based), que suelen ser más eficientes en SQL Server.

Conclusión

El uso de variables tipo tabla con IDENTITY y ciclos WHILE es una alternativa sencilla y efectiva para iterar datos sin recurrir a cursores ni tablas temporales.

No reemplaza todos los escenarios, pero definitivamente es una herramienta más que vale la pena tener en tu arsenal como desarrollador.