Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=,
<, <= , >, >= or when the subquery is used as an expression. (error 512) means a
subquery that you compared with =, or used as a single column value, found more than
one row. Replace = with IN or EXISTS, or make the subquery
return exactly one row.
Decide first which you meant. If several matches are valid, IN or
EXISTS is the fix. If there should only ever be one, the data or the subquery's
filter is wrong, and hiding it with TOP 1 would pick an arbitrary row.
The error
SELECT FullName
FROM dbo.Guests
WHERE Id = (SELECT GuestId FROM dbo.Bookings WHERE RoomNo = 204);
Msg 512, Level 16, State 1, Server MACHINE\LOCALDB#EAD42A01, Line 2
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Why it happens
A subquery after = is a scalar subquery: SQL Server treats it as one value. Room 204
had two bookings, for Maria Garcia and David Chen, so the subquery produced two
GuestId values and there was no single value to compare with. Unlike errors 4104 or
8120, this is a run-time error. The query compiles, and it only fails when the data gives more
than one row, which is why it often appears weeks after the code shipped, on the first day two
rows match.
The same message comes from a subquery used as a column. This query asks for one
GuestId per booking, and the two bookings of room 204 broke it the same way:
SELECT RoomNo,
(SELECT GuestId FROM dbo.Bookings AS b2 WHERE b2.RoomNo = b.RoomNo) AS GuestId
FROM dbo.Bookings AS b;
Msg 512, Level 16, State 1, Server MACHINE\LOCALDB#EAD42A01, Line 2
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The fix
-- fix A: IN accepts any number of rows
SELECT FullName
FROM dbo.Guests
WHERE Id IN (SELECT GuestId FROM dbo.Bookings WHERE RoomNo = 204)
ORDER BY FullName;
GO
-- fix B: EXISTS, the same answer
SELECT g.FullName
FROM dbo.Guests AS g
WHERE EXISTS (SELECT 1 FROM dbo.Bookings AS b WHERE b.GuestId = g.Id AND b.RoomNo = 204)
ORDER BY g.FullName;
Both returned David Chen and Maria Garcia. IN reads most naturally when you compare
one column; EXISTS is the general form and handles conditions on several columns.
For a subquery used as a column, the fix is a JOIN that produces one output row per
match, or an aggregate such as MAX or COUNT inside the subquery when one
value per row is really what you want.
How it was reproduced
One script run with sqlcmd -S "(localdb)\MSSQLLocalDB" -d fix8_lab -I -i e512.sql on
SQL Server 2022 LocalDB 16.0.1210.3 and sqlcmd 16.0.1000.6, in a throwaway database
fix8_lab created for the test and dropped afterwards. A guests table, a bookings table
with a foreign key, three fictional guests and three bookings, two of them for room 204.
Frequently asked
- What does 'Subquery returned more than 1 value' mean?
- SQL Server error 512 means a subquery used as a single value, after = or < or as a column in the select list, returned two or more rows when the statement ran.
- Should I use IN or TOP 1 to fix error 512?
- Use IN or EXISTS when several matching rows are valid. TOP 1 without ORDER BY returns an arbitrary row and hides a data problem, so use it only when any one match is acceptable.
- Why did my query work yesterday and fail with error 512 today?
- The error depends on the data. The query compiles fine and only fails on the day the subquery first finds two matching rows, for example a second booking for the same room.
More decoded errors in the Fixes category.