Cursor no PostgreSQL
Ao fazer um SELECT no PostgreSQL, você recebe sempre uma lista estática de linhas com suas respectivas colunas.
Mas e se você precisasse fazer algum tipo de processamento linha-a-linha de forma eficiente? Se você precisasse percorrer cada linha de um retorno de um SELECT e executar uma função e ir atualizando uma variável dentro de uma stored procedure? (Em outras palavras, como é que podemos fazer um loop de for dentro do PostgreSQL?)
O CURSOR te permite fazer isso!
Imagine que o retorno de um SELECT é um grande array (ou vetor, ou lista, como quiser). O cursor é uma variável que guarda o índice de UMA linha. Você pode ir avançando ou retrocedendo o cursor como desejar.
As operações de movimentação do cursor são:
NEXT
Avança o cursor para a próxima linha do SELECT
PRIOR
Retorna o cursor para a linha anterior do SELECT
FIRST
Envia o cursor para a primeira linha do SELECT
LAST
Envia o cursor para a última linha do SELECT
ABSOLUTE count
Envia o cursor para a linha informada no "count"
RELATIVE count
Envia o cursor para: "count" +
FORWARD
BACKWARD
Um exemplo simples:
-- Criando uma função que retorna um cursor com o nome enviado por parâmetro e o opera sobre a query informada por parâmetro.CREATE FUNCTION open_cursor(cursor_name REFCURSOR, query TEXT) RETURNS refcursor AS ' BEGIN OPEN cursor_name FOR EXECUTE query; RETURN cursor_name; END; ' LANGUAGE plpgsql; -- Aqui veremos o comportamento do cursor. Você não necessariamente precisa usar ele via SQL normal. Você pode usá-lo dentro de uma stored procedure. Estamos fazendo isso aqui apenas para facilitar a visualização do comportamento do cursor. -- Execute o BEGIN; SELECT... FETCH... apenas -- Na sequência, BEGIN; SELECT open_cursor('wow', 'SELECT * FROM veiculos ORDER BY line_id ASC, vehicle_id ASC, date_time ASC;'); FETCH NEXT IN wow; FETCH LAST IN wow; FETCH FIRST IN wow; FETCH ABSOLUTE 5 in wow; COMMIT;
Referências
Documentação oficial sobre cursors
https://www.postgresql.org/docs/current/plpgsql-cursors.html
PostgreSQL Tutorial sobre cursors
http://www.postgresqltutorial.com/plpgsql-cursor/