Fix Msg 512 “Subquery returned more than 1 value” in SQL Server

If you get error Msg 512 that reads “Subquery returned more than 1 value…” in SQL Server, it’s because you’re using a subquery that returns more than one value in a scenario where this is not allowed.

Example of Error

Suppose we have the following two tables:

SELECT * FROM Dogs;

SELECT * FROM Cats;

Result:

+---------+-----------+
| DogId   | DogName   |
|---------+-----------|
| 1       | Fetch     |
| 2       | Fluffy    |
| 3       | Wag       |
| 4       | Fluffy    |
+---------+-----------+

+---------+-----------+
| CatId   | CatName   |
|---------+-----------|
| 1       | Meow      |
| 2       | Fluffy    |
| 3       | Scratch   |
+---------+-----------+

And we run the following query against those two tables:

SELECT * FROM Dogs 
WHERE DogName = ( SELECT CatName FROM Cats );

Result:

Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

We can see that it resulted in error Msg 512.

This error message explicitly tells us that the “Subquery returned more than 1 value” and that “This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression”.

The solution to this will depend on what you’re trying to do in the query. Below are a couple of options for resolving this issue.

Solution 1

One way to deal with this is to use a different operator. What I mean is, use an operator other than =, !=, <, <= , >, or >=.

Here’s an example that uses the IN operator:

SELECT * FROM Dogs 
WHERE DogName IN ( SELECT CatName FROM Cats );

Result:

+---------+-----------+
| DogId   | DogName   |
|---------+-----------|
| 2       | Fluffy    |
| 4       | Fluffy    |
+---------+-----------+

Solution 2

Another option is to keep the equals (=) operator (or whichever operator is in the original query), but change the subquery.

Here’s an example of changing the subquery, while keeping the equals operator:

SELECT * FROM Dogs 
WHERE DogName = ( SELECT CatName FROM Cats WHERE CatId = 2 );

Result:

+---------+-----------+
| DogId   | DogName   |
|---------+-----------|
| 2       | Fluffy    |
| 4       | Fluffy    |
+---------+-----------+

In this case the subquery returned one value only, and the equals operator was fine with that.

Solution 3

Note that the above subqueries only return one column. If the subqueries returned multiple columns, we’d need to change the outer query so that it uses the EXISTS operator.

Example:

SELECT * FROM Dogs d
WHERE EXISTS ( SELECT * FROM Cats c WHERE c.CatName = d.DogName );

Result:

+---------+-----------+
| DogId   | DogName   |
|---------+-----------|
| 2       | Fluffy    |
| 4       | Fluffy    |
+---------+-----------+

If we didn’t change it to use the EXISTS operator, then we’d probably get error message 116.