Db2 SQLCODE

SQLCODE -504: Cursor name not declared

SQLCODE -504 (SQLSTATE 34000) means an OPEN, FETCH, CLOSE or positioned UPDATE or DELETE names a cursor that Db2 doesn't know in this program. The cursor was never declared, is misspelled, or was declared in the wrong place.

Other names for this code

Also written as SQL -504, SQLCODE=-504, SQLCODE = -504, db2 -504, sqlstate 34000, SQL0504N, db2 cursor not declared, db2 cursor not defined, SQL0504, cursor name is not declared.

What it means

Every cursor needs a DECLARE CURSOR in the same program before any statement uses it. For static SQL the precompiler checks this as it reads the source from top to bottom, so the DECLARE has to come before the first OPEN, FETCH or CLOSE in the source text. In COBOL, putting the DECLARE in WORKING-STORAGE meets that rule.

Cursors are local to the program, or more exactly to its package. A cursor declared in one program can't be opened or fetched in another, even if both run in the same job and use the same plan.

Dynamic cursors also need a DECLARE, written against a statement name, for example DECLARE CSR1 CURSOR FOR STMT1. Cursors that read stored procedure result sets are created with ALLOCATE CURSOR instead. The message names the cursor. If it shows the name as <UNKNOWN>, the DECLARE or ALLOCATE itself failed, so check the precompile output for a warning on it.

Common causes

  • The cursor name is misspelled in the OPEN, FETCH or CLOSE, or differs by a hyphen or a digit from the DECLARE.
  • The DECLARE CURSOR comes after the first statement that uses it in the source, for example at the end of the PROCEDURE DIVISION.
  • The cursor is declared in a different program, and this program tries to fetch from it.
  • The DECLARE is in a copybook or a section that isn't included in this build.
  • For dynamic SQL, the program prepared a statement but never declared a cursor for it.
  • For stored procedure result sets, the program fetches from a cursor before ALLOCATE CURSOR, or after the ALLOCATE failed.
  • An allocated result set cursor was freed by a CLOSE, a ROLLBACK, a COMMIT (when the procedure's cursor wasn't WITH HOLD) or a second CALL of the procedure, and the program then used it again.
  • A positioned UPDATE or DELETE names an allocated result set cursor, which Db2 doesn't support.

How to find the problem

  1. Read the precompiler listing. It names the cursor and the statement that referred to it.
  2. Search the source for DECLARE and the cursor name, and compare the spelling character by character.
  3. Check where the DECLARE sits in the source compared with the first OPEN.
  4. For result set cursors, check the SQLCODE from ASSOCIATE LOCATORS and ALLOCATE CURSOR.

How to fix it

  • Correct the spelling, or add the missing DECLARE CURSOR.
  • Move the DECLARE into WORKING-STORAGE, or anywhere before the first use in the source.
  • Keep each cursor's DECLARE, OPEN, FETCH and CLOSE in the same program. If another program needs the rows, pass them as data or give it its own cursor.
  • Check the result of ALLOCATE CURSOR before fetching from a result set cursor.
  • After a COMMIT, ROLLBACK, CLOSE or new CALL, call the procedure again if needed and repeat ASSOCIATE LOCATORS and ALLOCATE CURSOR. Declaring the procedure's cursor WITH HOLD keeps it across a COMMIT.

IBM documentation

IBM documentation: -504. Use the documentation for your installed release.

Report a correction to WND Software.

Questions

Can I declare a cursor in WORKING-STORAGE?

Yes. COBOL allows DECLARE CURSOR in WORKING-STORAGE or in the PROCEDURE DIVISION, as long as it comes before the first statement that uses the cursor.

Can a called subprogram fetch from my cursor?

No. A cursor is known only in the program that declares it. Pass the data, or give the subprogram its own cursor.

Is it the same on Db2 for LUW and IBM i?

Yes. Db2 for LUW reports SQL0504N and IBM i reports SQL0504, both with SQLSTATE 34000.