tSQL error “Subquery returned more than 1 value…” does not throw an exception in SqlClient

StackOverflow https://stackoverflow.com/questions/11155739

  •  16-06-2021
  •  | 
  •  

Frage

Intro

I have an issue with the SqlClient in .Net 4.0.30319 SP1Rel, in which no Exception is thrown when my stored procedure proceduces the following error:

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

I've created an tiny program and stored proc that will demonstrate this. Sql Server version is 9.0.4053.

Code sample

Stored procedure

create proc test
as
select case (select 1 union select 2) when 1 then 1 else 2 end

.Net Console app

using System;
using System.Data;
using System.Data.SqlClient;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            SqlConnection conn = new SqlConnection("<your connection string>");
            conn.Open();

            SqlCommand cmd = new SqlCommand("test", conn);
            cmd.CommandType = CommandType.StoredProcedure;
            try
            {
                SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                Console.WriteLine("Finished");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            Console.ReadKey();
        }
    }
}

Running this application just writes 'Finished' to the console.

Running the stored procedure 'test' in de SQL Server Management Studio will report the error in the result pane like:

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

Expected behaviour

Replacing the stored proc by the following example, will give an expected System.Data.SqlClient.SqlException.

Raiserror

alter proc test
as
raiserror('Not good at all!', 16, 1)

Alternative issues

Some other definitions I have found don't throw an exception as well.

Raiserror after

alter proc test
as
select case (select 1 union select 2) when 1 then 1 else 2 end
raiserror('Not good at all!', 16, 1)

This suggests that the select-statement stops execution of the stored procedure.

Divide by zero

alter proc test
as
select 1/0

My conclusion is that the SqlClient does not propertly recognize the error state of the tSql batch. Has anybody encountered this and found a solution? I always trusted on the .Net framework to throw an exception on any tSql error.

War es hilfreich?

Lösung

Thanks to the helpful and swift comment of Martin, I found the cause of this strange behaviour.

In the past, one of the programmers wrapped the reads on the reader in a test to see if there were any rows at all, like this:

SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);

if (reader.HasRows)
{
    while (reader.Read()) { /* Do Something */ }
}

I don't know why, as the read() method will return false on the first call, when there are no rows.

Anyway, when an error occurred in the tSQL, the HasRows property returned false and the Read() method was never called. Due to that, SQL errors where not revealed to the SqlClient and no exception was thrown.

You can add this code-snippet to the sample project, just after ExecuteReader, with or without test for HasRows, and see the effect.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top