Tabla de contenidos
Se ha recopilado información sobre las operaciones básicas de cursor en PL/pgSQL de PostgreSQL.
Entorno
- psql 9.6
- PostgreSQL 9.3
Cursor
En términos generales, se utiliza cuando se desea realizar un procesamiento secuencial para cada registro recuperado con SELECT
.
Definición y uso de un cursor
Hay varias formas de escribir un cursor, pero comencemos con lo básico. En Oracle se llama cursor explícito, y en la documentación de PostgreSQL se refiere como Bound Cursor.
Definimos un cursor con CURSOR
y preparamos una variable de tipo RECORD
. Utilizamos LOOP
para realizar el procesamiento en todas las filas del resultado de SELECT
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
DO $$ DECLARE C CURSOR FOR SELECT * FROM table_name WHERE some_condition = TRUE; CR RECORD; BEGIN OPEN C; LOOP FETCH C INTO CR; IF NOT FOUND THEN EXIT; END IF; RAISE NOTICE '%', CR.id; END LOOP; CLOSE C; END$$; |
La palabra FOR
después de CURSOR
también puede ser reemplazada por IS
. Aunque en la documentación oficial solo se menciona la escritura con FOR
, también funcionará si se cambia a IS
.
Abrimos el cursor, colocamos las filas del resultado de la consulta en la variable (en este caso, CR
) y realizamos el procesamiento en todas las filas del cursor. Cuando el cursor ha procesado la última fila, salimos del bucle con EXIT
. Finalmente, cerramos el cursor abierto.
La sección de EXIT
usa una estructura IF
para la condición, pero si solo desea ejecutar EXIT
, puede escribirlo de manera más concisa con EXIT WHEN NOT FOUND;
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
DO $$ DECLARE C CURSOR FOR SELECT * FROM table_name WHERE some_condition = TRUE; CR RECORD; BEGIN OPEN C; LOOP FETCH C INTO CR; EXIT WHEN NOT FOUND; RAISE NOTICE '%', CR.id; END LOOP; CLOSE C; END$$; |
Además, el timing de FETCH
es simple, por lo que se puede acortar más el código.
1 2 3 4 5 6 7 8 9 10 11 |
DO $$ DECLARE C CURSOR FOR SELECT * FROM table_name WHERE condition = true; BEGIN FOR CR IN C LOOP RAISE NOTICE '%', CR.id; END LOOP; END$$; |
En este caso, la variable CR
que almacena el registro solo es válida dentro del bucle.
Uso de parámetros con el cursor
Al igual que una función en un lenguaje de programación, un cursor puede tomar parámetros.
1 2 3 4 5 6 7 8 9 10 11 12 |
DO $$ DECLARE C CURSOR( I_MIN_ID INTEGER, I_MAX_ID INTEGER) FOR SELECT * FROM table_name WHERE id BETWEEN I_MIN_ID AND I_MAX_ID; BEGIN FOR CR IN C(10, 20) LOOP RAISE NOTICE '%', CR.id; END LOOP; END$$; |
Uso de un cursor sin declararlo
Esto podría considerarse una aplicación avanzada de cursor. Personalmente, no lo uso con frecuencia. En Oracle se llama cursor implícito.
1 2 3 4 5 6 7 8 |
DO $$ DECLARE CR RECORD; BEGIN FOR CR IN (SELECT * FROM MEMBERS WHERE ID BETWEEN 1 AND 10) LOOP RAISE NOTICE '%', CR.id; END LOOP; END$$; |
No se declara una variable de cursor. Sin embargo, se debe declarar una variable de registro. (En Oracle PL/SQL, no era necesario declarar una variable de registro).