12

I am trying to learn basic cursors using PostgreSQL. This is my script:

DECLARE cur_employees CURSOR FOR
  SELECT *
  FROM   employee

CLOSE cur_employees 

I want to traverse the list and output those which are active. Where should I start?

6
  • 1
    Start by adding a WHERE clause selecting active ones. Commented Dec 24, 2011 at 12:41
  • 2
    Read the chapter about cursors in the manual. Commented Dec 24, 2011 at 14:01
  • i did as you told me: DECLARE cur_employees CURSOR FOR SELECT * FROM employee where active = 'active' CLOSE cur_employees but i am getting the following error: Commented Dec 24, 2011 at 14:39
  • ERROR: syntax error at or near "CLOSE" LINE 6: CLOSE cur_employees ^ ********** Error ********** ERROR: syntax error at or near "CLOSE" SQL state: 42601 Commented Dec 24, 2011 at 14:39
  • @Karl: Is your question targeted on cursors of the SQL language or on cursors of the pl/pgsql language? Commented Dec 25, 2011 at 22:16

2 Answers 2

28

You very rarely want to explicitly use cursors at all in PostgreSQL, even when processing query results in plpgsql. This is a marked contrast from many other SQL databases where they are used almost all the time.

In plpgsql you could simply write something like:

DECLARE
  emp employee%rowtype;
BEGIN
  FOR emp IN SELECT * FROM employee LOOP
    IF emp.active THEN
      RAISE INFO 'Active: %', emp.employee_id
    END IF;
  END LOOP;
END

In the above, the plpgsql language handler deals with opening, binding, fetching and closing itself (more on declarations, and control structures).

With PostgreSQL from 9.0, you can simply drop into executing plpgsql using a "DO" block. For prior versions, you need to create a function and select it. If you're looking for the PostgreSQL equivalent of, for example, iterating through a result with a cursor on SQL Server, that's what it is. Note that iteration etc. are not part of the SQL dialect, only part of plpgsql (or any of the other emebedded languages).

The "DECLARE CURSOR xxx" syntax at the SQL level can be used like this:

DECLARE cur_employees CURSOR FOR SELECT * FROM employee;
FETCH NEXT FROM cur_employees;
// etc..
CLOSE cur_employees;

This can be used to carefully get just part of the query result set. However, it's unusual to use these, since usually your client driver will provide some sort of functionality to do this (e.g. scrollable result sets in JDBC). You can also return cursors from functions similar to Oracle, although again that's a comparatively rare use case.

Sign up to request clarification or add additional context in comments.

2 Comments

And remember that 90+% of what people try to use cusors for would be better handled with set based operations. You should virtually never think of looping through a data set and no one except an experienced dba should consider writing a cursor. This is one technique that you should not learn until you are very senior and know when it is appropriate. If you are just learning SQl, skip this one for about ten years.
I would go further with the comment about using cursors. If you’re using a cursor, you’re probably doing it wrong. SQL is built on sets, and the DBMS is optimised around that; it tries to work with an entire data set, and you would have to have a damned good reason to force it to work with one row at a time. Apart from esoteric cases of database maintenance, you might consider using a cursor if data in one row really depends on the values in the previous row, which is probably a badly designed table. Otherwise, cursors might be used by programmers who don’t understand SQL philosophy.
0

Generally, one has a DECLARE for the cursor, then an OPEN of the cursor (which materializes the result set), multiple FETCH operations to retrieve the rows from the result set individually, and then one does a CLOSE of the cursor.

You appear to have a DECLARE followed by a CLOSE. Thus your syntax error, as you never did an OPEN.

1 Comment

Hm. Karl did not mention whether he wants to use the cursors with SQL or with pl/pgsql. For SQL there is no OPEN, because that is implicitly done by the DECLARE.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.