- Each cursor is a stateful SQL object that is referred to by a unique name.
- Each cursor requires holding open its own dedicated (read-only) .
- Each cursor operates on a snapshot of the database at the moment that cursor is opened.
Synopsis
Examples
These examples assume the presence of the .Use a cursor
Use a holdable cursor
By default, a cursor closes when the transaction ends. TheWITH HOLD clause defines a holdable cursor, which behaves as follows:
- A holdable cursor writes its results into a buffer, and stays open after a transaction commits.
- If a transaction aborts, all cursors opened within that transaction are also rolled back. However, holdable cursors from previously committed transactions remain open.
- A holdable cursor can be opened in both explicit and implicit transactions.
- If a holdable cursor results in an error as it is being persisted, it will cause the current transaction (implicit or explicit) to be rolled back.
WITH HOLD to access data across multiple transactions without redefining the cursor.
The
WITHOUT HOLD clause specifies the default non-holdable cursor behavior.- Explicit
- Implicit
Start a transaction:Declare a cursor using Fetch the first two rows from the cursor:Commit the transaction:Declare a cursor using Fetch the first two rows from the cursor:Continue fetching rows from the cursor:Close the cursor:
WITH HOLD to keep it open after the transaction commits:WITH HOLD to keep it open after the transaction commits:View all open cursors
Known limitations
CockroachDB implements SQL cursor support with the following limitations:DECLAREonly supports forward cursors. Reverse cursors created withDECLARE SCROLLare not supported.FETCHsupports forward, relative, and absolute variants, but only for forward cursors.BINARY CURSOR, which returns data in the Postgres binary format, is not supported.- Scrollable cursor (also known as reverse
FETCH) is not supported. - with a cursor is not supported.
- Respect for is not supported. Cursor definitions do not disappear properly if rolled back to a
SAVEPOINTfrom before they were created.
Differences between cursors and keyset pagination
Cursors are stateful objects that use more database resources than keyset pagination, since each cursor holds open a transaction. However, they are easier to use, and make it easier to get consistent results without having to write complex queries from your application logic. They do not require that the results be returned in a particular order (that is, you don’t have to include anORDER BY clause), which makes them more flexible.
Keyset pagination queries are usually much faster than cursors since they order by indexed columns. However, in order to get that performance they require that you return results in some defined order that can be calculated by your application’s queries. Because that ordering involves calculating the start/end point of pages of results based on an indexed key, they require more care to write correctly.

