Cursores
Un cursor es una zona de memoria donde se traen datos para trabajar con ellos fila a fila.
Declaración:
DECLARE nombreCursor FOR sentenciaSQL;

Con OPEN c_alumnos se abre el cursor posicionándolo al inicio de los datos. Se declaran variables para almacenar los datos leídos en cada iteración.
Sintaxis del FETCH:
FETCH nombreCursor INTO variableDondeGuardar;

Lee fila a fila, almacenando cada campo en la variable correspondiente.
Ejemplo completo con control de error NOT FOUND:

Al intentar leer más allá del final del conjunto, MySQL genera el error 1329. Se controla declarando un manejador antes del cursor:
DECLARE CONTINUE HANDLER FOR NOT FOUND SET variable = 1;
Se declara previamente: DECLARE v_ultima_fila INT DEFAULT 0;
El programa cierra el cursor con: CLOSE nombreCursor;

Cursores con parámetros
El parámetro se pasa mediante la cláusula WHERE de la sentencia SQL del cursor, permitiendo filtrar los resultados de forma dinámica:

Cursores anidados
Combina un cursor principal (c_centros) con otro interno (c_departamentos). El procedimiento abre el cursor principal, recorre sus filas en un bucle y, dentro de cada iteración, abre el segundo cursor para procesar los datos relacionados:

Es importante reiniciar la variable de control de última fila después de recorrer el cursor interno para que el bucle exterior funcione correctamente.

Nota: En el segundo cursor anidado hay que asegurarse de que la variable de filtro (
v_numce) tenga el valor correcto antes de abrir el cursor. Una alternativa es usarINNER JOINen la consulta principal.