Navigating large datasets quickly and effectively is critical when it comes to database management systems. One of PostgreSQL's core features, cursors are vital tools for accurately navigating and modifying query results. During the migration from Oracle to PostgreSQL, managing data efficiently using PostgreSQL Cursors for precise navigation is crucial. This article is the first in a series of three, where we will explore the three different types of cursors you can use with PostgreSQL. Each article will focus on one cursor type, making it easy to understand and apply them in PostgreSQL. In this article, we will discuss the type of Cursors in PostgreSQL and how we can navigate through data with precision using Scrollable Cursors in PostgreSQL.
Data Navigation with PostgreSQL Cursors.
If interested, take a look at our article on PostgreSQL Summary and Achievements in 2023.
A quick Architecture Audit can save hours of troubleshooting later.
Try it Now!Let HexaRocket simplify it - migrate smarter, faster, and stress-free.
Contact us Today!HexaRocket performs end-to-end database migrations and replication seamlessly between Oracle, SQL Server, MySQL, MariaDB, and PostgreSQL.
Try Today!A cursor is a database object used to retrieve rows from a result set one at a time, rather than fetching the entire result set at once. They provide a way to iterate through the rows of a result set, allowing controlled and sequential access to the data. It acts as a pointer to a specific row within a set of rows and allows operations like traversal, reading, updating, and deleting individual rows.
In PostgreSQL, various cursor types offer flexibility in managing query results. Forward-only cursors, enable sequential navigation through result sets but restrict movement to forward direction only. Scrollable cursors provide bidirectional movement, allowing data retrieval in both forward and backward directions, enhancing navigation within result sets. Additionally, PostgreSQL supports cursor holdability, enabling cursors to remain open even after committing a transaction, ensuring continued access to results.
If you are looking for any assistance around PostgreSQL, click here for personalized expertise to elevate your database performance and meet your unique business needs.
Scrollable Cursors enable movement both forward and backward within query results, offering a more dynamic approach to data retrieval and manipulation compared to traditional forward-only cursors. These cursors empower developers to fetch rows in a non-sequential manner, providing greater flexibility in accessing and processing data sets.
Consider a table named employees. Let's prepare the cursor to navigate through all records within the "employees" table
DECLARE my_cursor SCROLL CURSOR FOR SELECT * FROM employees;
Cursor can be opened using the following command, it will make the cursor available to fetch the data from it.
OPEN my_cursor;
FETCH NEXT NEXT will retrieve the next row in the result set and advances the cursor position forward. If the row value exists, it will print it; otherwise, NULL will be produced.
FETCH NEXT FROM my_cursor;
Move backwards using PRIOR PRIOR retrieves the previous row in the result set and moves the cursor position backward.
FETCH PRIOR FROM my_cursor;
To get the FIRST row FIRST takes the cursor to the first position and displays the first row in the result set.
FETCH FIRST FROM my_cursor;
Using RELATIVE It moves the cursor to a relative position from its current location in the result set and retrieves the row.
FETCH RELATIVE 2 FROM my_cursor;
Negative numbering indicates to iterate backwards. It will retrieve the previous row of the result set which is same as the behavior of FETCH PRIOR
FETCH RELATIVE -1 FROM my_cursor;
MOVE moves the pointer but doesn't get any info. MOVE functions in the same way as FETCH, with the exception that it just moves the cursor and doesn't return the row it went to. By default, MOVE moves the pointer to the next row.
MOVE my_cursor;
RELATIVE, ABSOLUTE, FIRST, LAST can also be used with MOVE.
Let's write an anonymous block to fetch one record from employees table and print it to the console using FETCH command.
DO $$
DECLARE
emp_record employees%ROWTYPE;
emp_cursor SCROLL CURSOR FOR SELECT * FROM employees LIMIT 1;
BEGIN
OPEN emp_cursor;
FETCH emp_cursor INTO emp_record;
CLOSE emp_cursor;
RAISE NOTICE 'Employee: %', emp_record; -- Prints employee data to the console
END $$;
Seeking specialized PostgreSQL guidance? Get specialized advice for effective data management, query tuning, and database optimization. Click here for personalized expertise to elevate your database performance and meet your unique business needs.
Subscribe to our Newsletters and Stay tuned for more interesting topics.

Jagadeesh Panuganti is a full-stack Software Engineer at HexaCluster, specializing in building and deploying scalable cloud-native applications. With expertise in React, Node.js, Go, and PostgreSQL, he focuses on creating robust solutions using microservices architecture on cloud platforms like Azure and AWS. He has a passion for designing secure, efficient systems and CI/CD pipelines.
Start your migration journey 🚀
start your migration journey with our expert team
Database & Application Migration Assessment Tool
End-to-End Database Migration & Modernization Tool
Database Code Object Conversion to PostgreSQL
MyBatis Mapper Conversion to PostgreSQL
Enterprise Data Replication & Live CDC
Oracle Compatibility Layer for PostgreSQL