A cursor provides sequential, controlled access to the rows returned by a SELECT statement. Unlike set-based operations that act on all rows at once, a cursor lets procedural code handle one row at a time, making it useful for complex business logic, row-by-row calculations, or conditional updates that cannot be expressed easily in pure SQL.Lifecycle1. DECLARE CURSOR associates the cursor name with a SELECT statement and optional attributes (SCROLL, INSENSITIVE, READ ONLY, FOR UPDATE, etc.).2. OPEN executes the underlying query and materializes the result set.3. FETCH retrieves the next, prior, absolute, or relative row into program variables.4. (Optional) UPDATE or DELETE WHERE CURRENT OF modifies or removes the current row.5. CLOSE releases resources.Caveats- Cursors are slower than set-based operations and should be used only when necessary.- Some attributes vary by vendor; always check dialect documentation.- Without proper closing, cursors can leak memory or locks.- In autocommit mode, some databases close cursors automatically at commit; others require WITH HOLD to survive commits.
cursor_name
(identifier) - Name of the cursor objectSCROLL/NO SCROLL
(keyword) - Whether backward movement is allowedWITH/WITHOUT HOLD
(keyword) - Whether the cursor remains open after COMMITFOR READ ONLY
(keyword) - Disallow positioned updatesFOR UPDATE [OF cols]
(keyword) - Allow positioned updates on listed columnsselect_statement
(SQL text) - Query that defines the result setDECLARE, FETCH, OPEN, CLOSE, FOR UPDATE, WHILE loops, Stored Procedures, Transactions
SQL-92
Use a cursor only when set-based SQL cannot achieve the required per-row logic. Examples include conditional updates, row-driven API calls, or incremental ETL tasks.
Typically no. Databases lock only the rows fetched, but behavior depends on isolation level and whether FOR UPDATE is present.
Select only required columns, declare READ ONLY when possible, fetch multiple rows per round-trip if the dialect supports it, and close the cursor promptly.
Only if declared WITH HOLD and your database supports holdable cursors. Otherwise, a commit ends the cursor’s life.