Mainframe Path Start learning free
CoreError and abend codes-811

SQLCODE -811 — more than one row returned

A singleton SELECT INTO or a scalar subquery found more than one row. The data or the predicate is not as unique as the program assumed.

What happened

A program that has worked for years suddenly fails on a SELECT ... INTO, often after a data change, conversion or new business rule.

Program output via DSNTIAR (illustrative)
DSNT408I SQLCODE = -811, ERROR:  THE RESULT OF AN EMBEDDED SELECT
         STATEMENT OR A SUBSELECT IN THE SET CLAUSE OF AN UPDATE
         STATEMENT IS A TABLE OF MORE THAN ONE ROW, OR THE RESULT OF
         A SUBQUERY OF A BASIC PREDICATE IS MORE THAN ONE VALUE
DSNT418I SQLSTATE   = 21000 SQLSTATE RETURN CODE

What it means

SELECT ... INTO can only return one row into host variables. A subquery used with =, <, > and similar must return one value. When more than one qualifies, Db2 returns -811 with SQLSTATE 21000. Do not rely on the host variables after a -811.

This code has no useful SQLERRMC tokens naming an object. You identify the statement from the program: its error routine should log the statement number or paragraph name.

Typical causes

Symptoms

It fails for particular keys only, every time those keys are read. Different from -803 (a write is rejected) and from +100 (no row found). Some old programs treat -811 as success; check the code before calling it a new problem.

Where to look

How to diagnose

  1. Find the failing statement from the program log and listing.
  2. Re-run the same SELECT in a query tool with the logged key values, using COUNT(*).
  3. Look at the extra rows. Are they valid business data or bad data?
  4. Compare the predicate with the table's unique key columns.
  5. Ask when and how the extra rows arrived.

How to fix

If the extra rows are wrong, the data owner corrects them and the job is rerun. If they are valid, change the SQL: add the missing predicate, use a cursor and process all rows, or pick one row deliberately with ORDER BY ... FETCH FIRST 1 ROW ONLY. For existence checks use EXISTS or FETCH FIRST 1 ROW ONLY instead of relying on -811.

To turn the raw SQLCA into readable text, call DSNTIAR (DSNTIAC in CICS) with the SQLCA and a message buffer, or use GET DIAGNOSTICS to fetch MESSAGE_TEXT, RETURNED_SQLSTATE and DB2_RETURNED_SQLCODE. Either way, write the full message to the job log before the program ends.

How to prevent

Production considerations

Interview question

What causes SQLCODE -811 and how would you fix it properly?

Stuck on something else?
Ask the community or search the full course.

Ask a question