Informix Error -284: A subquery has returned not exactly one row.
Cause and resolution
A subquery has returned not exactly one row.
A subquery that is used in an expression in the place of a literal value must return only a single row and a single column. In this statement, a subquery has returned more than one row, and the database server cannot choose which returned value to use in the expression. You can ensure that a subquery will always return a single row. Use a WHERE clause that tests for equality on a column that has a unique index. Or select only an aggregate function. Review the subqueries, and check that they can return only a single row.
This error can also occur when you use a singleton SELECT statement to retrieve multiple rows. You must use the DECLARE/OPEN/FETCH series of statements or the EXECUTE INTO statement to retrieve multiple rows.
Oninit® Troubleshooting Guidance
Reasons / Common Causes
-284 is one of the most common everyday query-construction errors: a subquery used in place of a single literal value in an expression must return exactly one row and one column, and this one returned more than one.
- A scalar subquery whose
WHEREclause doesn't uniquely constrain the result, returning multiple rows when the surrounding expression expected exactly one. - Using a singleton
SELECT(a plainSELECT ... INTOexpecting one row) against a query that can actually return multiple rows — the proper approach for a genuinely multi-row result isDECLARE/OPEN/FETCH(a cursor), not a singleton select. - A
WHEREclause condition that isn't actually unique, when the code assumes it uniquely identifies one row — filtering on a column that isn't backed by a unique constraint or index. - Data growth breaking a previously-safe assumption — a subquery or singleton select that worked when only one row ever matched historically, failing once a second matching row appears (an email column assumed unique but never actually constrained that way, for example — see -100 for the broader uniqueness-assumption theme).
Solutions / Resolution
- Ensure the subquery returns a single row by using a
WHEREclause backed by a unique index equality test, per the official guidance. - Alternatively, select only an aggregate function (
MAX,MIN,COUNT, and similar) if a single summary value is genuinely all that's needed — aggregates always collapse to one row. - If genuinely expecting multiple rows, use
DECLARE/OPEN/FETCH(a cursor) instead of a singletonSELECT. - Review whether the assumed uniqueness actually holds, and enforce it with a real unique constraint or index if it should — rather than relying on an assumption that happens to be true today.
Examples
A subquery without a unique constraint
SELECT name, (SELECT total FROM orders WHERE customer_id = c.id) AS last_order
FROM customer c;
-- -284: a customer with more than one order returns multiple
-- rows from the subquery
Fix — use an aggregate if a single summary value is what's needed:
SELECT name, (SELECT MAX(total) FROM orders WHERE customer_id = c.id) AS max_order
FROM customer c;
Or constrain to a genuinely unique row if that's the actual intent:
SELECT name, (SELECT total FROM orders WHERE order_id = c.latest_order_id) AS last_order
FROM customer c;
Singleton SELECT misuse
SELECT * INTO :rec FROM orders WHERE status = 'pending';
-- -284: more than one pending order exists
Fix — use a cursor if multiple rows are genuinely expected:
DECLARE cur1 CURSOR FOR SELECT * FROM orders WHERE status = 'pending';
OPEN cur1;
FETCH cur1 INTO :rec;
Diagnostic Checks
- Test the subquery or singleton select independently to see how many rows it actually returns for the data in question.
- Review the
WHEREclause for whether it's genuinely backed by a unique index or constraint, rather than an assumption.
Related Errors / Related Topics
- -201 — "A syntax error has occurred." The general SQL-parsing-error family this fits into.
- -100 — "ISAM error: duplicate value for a record with unique key." Relevant to the underlying uniqueness-assumption theme — if a column was assumed unique but never actually constrained that way, this is the related enforcement mechanism worth adding.
Test the subquery independently first — it immediately reveals whether the "single row" assumption actually holds for the current data.