how do you check for no rows returned after ExecuteNonQuery for SELECT sql statement returns no rows??
-
2Can you please provide some context? Better yet, code? Does your `command` have parameters? – AJ. Nov 24 '10 at 17:25
4 Answers
The ExecuteNonQuery Method
returns the number of row(s) affected by either an INSERT
, an UPDATE
or a DELETE
. This method is to be used to perform DML (data manipulation language) statements as stated previously.
The ExecuteReader Method
will return the result set of a SELECT
. This method is to be used when you're querying for a bunch of results, such as rows from a table, view, whatever.
The ExecuteScalar Method
will return a single value in the first row, first column from a SELECT
statement. This method is to be used when you expect only one value from the query to be returned.
In short, that is normal that you have no results from a SELECT
statement while using the ExecuteNonQuery method. Use ExecuteReader instead. Using the ExecuteReader
method, will will get to know how many rows were returned through the instance of the SqlDataReader
object returned.
int rows = 0;
if (reader.HasRows)
while (reader.Read())
rows++;
return rows; // Returns the number of rows read from the reader.

- 23,773
- 22
- 96
- 162
-
@JLILIAmen Was this property available in 2010? This is the first time I ever heard of it. It's nice if it now has it. Thanks for the comment. – Will Marcouiller May 01 '18 at 11:41
I don't see any way to do this. Use ExecuteScalar
with select count(*) where
... to count the rows that match the criteria for your original SELECT query. Example below, paraphrased from here:
using (SqlCommand thisCommand =
new SqlCommand("SELECT COUNT(*) FROM Employee", thisConnection))
{
Console.WriteLine("Number of Employees is: {0}",
thisCommand.ExecuteScalar());
}
If you need the rows as well, you would already be using ExecuteReader
, I imagine.

- 53,498
- 9
- 91
- 140
Use the ExecuteReader
method instead. This returns a SqlDataReader
, which has a HasRows
property.
ExecuteNonQuery
shouldn't be used for SELECT
statements.

- 1,993
- 8
- 26
- 45

- 101
- 1
- 4
This is late, but I ran into this problem recently and thought it would be helpful for others coming in later (like me) seeking help with the same problem. Anyway, I believe you actually could use the ExecuteNonQuery they way you are trying to. BUT... you have to adjust your underlying SELECT query to a stored procedure instead that has SELECT query and an output parameter which is set to equal the row count.
As stated in the MSDN documentation:
Although the ExecuteNonQuery returns no rows, any output parameters or return values mapped to parameters are populated with data.
Given that, here's how I did it. By the way, I would love feedback from the experts out there if there are any flaws in this, but it seems to work for me.
First, your stored procedure should have two SELECT statements: one to return your dataset and another tied to an output parameter to return the record count:
CREATE PROCEDURE spMyStoredProcedure
(
@TotalRows int output
)
AS
BEGIN
SELECT * FROM MyTable; //see extra note about this line below.
SELECT @TotalRows COUNT(*) FROM MyTable;
END
Second, add this code (in vb.net, using SqlCommand etc..).
Dim cn As SqlConnection, cm As SqlCommand, dr As SqlDataReader
Dim myCount As Int32
cn = New SqlConnection("MyConnectionString")
cn.Open() //I open my connection beforehand, but a lot of people open it right before executing the queries. Not sure if it matters.
cm = New SqlCommand("spMyStoredProcedure", cn)
cm.CommandType = CommandType.StoredProcedure
cm.Parameters.Add("@TotalRows", SqlDbType.Int).Direction = ParameterDirection.Output
cm.ExecuteNonQuery()
myCount = CType(cm.Parameters("@TotalRows").Value, Integer)
If myCount > 0 Then
//Do something.
End If
dr = cm.ExecuteReader()
If dr.HasRows Then
//Return the actual query results using the stored procedure's 1st SELECT statement
End If
dr.Close()
cn.Close()
dr = Nothing
cm = Nothing
cn = Nothing
That's it.
Extra note. I assumed you may have wanted to get the "MyCount" amount to do something other than determining whether to continue returning you're query. The reason is because with this method, you don't really need to do that. Since I'm utilizing the "ExecuteReader" method after getting the count, I can determine whether to continue returning intended data set using the data reader's "HasRows" property. To return a data set, however, you need a SELECT statement which returns a data set, hence the reason for my 1st SELECT statement in my stored procedure.
By the way, the cool thing about this method of using the "ExecuteNonQuery" method is you can use it to get the total row count before closing the DataReader (you cannot read output parameters before closing the DataReader, which is what I was trying to do, this method gets around that). I'm not sure if there is a performance hit or a flaw in doing this to get around that issue, but like I said... it works for me. =D

- 1,240
- 3
- 26
- 44
-
Yes, there is a performance hit due to executing the SQL in the `SqlCommand` twice. And if there are DML statements, they will have executed twice. Also, there really is not reason to open the connection prior to executing the SqlCommand; it just means you are keeping the connection open longer. You could just move it to after the parameter declaration. And the Connection.Open() down through the last "End If" should be in a Try / Catch so that the Reader and Connection can be properly closed in a Finally block if an exception occurs. – Solomon Rutzky Jan 22 '15 at 20:47
-
Thanks for the input on where to place the Connection.Open. Makes sense. As for the performance hit, I understand that there will be a "hit" to some extent for running SqlCommand 2x. However, wouldn't the first execution be minimal since the ExecuteNonQuery doesn't return rows? I assumed the first would be fast since it's not pulling the whole data set. Therefore, the performance hit is minimal for the first SqlCommands (even if there where 1M underlying records). Please correct my understanding if I'm wrong. Haven't tested - just assumed that's how it worked given the definitions. – ptownbro Jan 23 '15 at 00:24
-
Not pulling back the results doesn't mean that SQL Server didn't need to find them. If you submit a query, SQL Server has to 1) parse it, 2) compile the execution plan, 3) execute it, and optionally 4) return the results. The first 3 steps happen even if you discard the pointer to the result set. Yes, you save the amount of time it takes to transfer the data, which is something, but not much. Given the caching done on execution plans and data pages, the first run is usually the longer one. Simple queries (no sorting/grouping) might be ok, but for the most part, this is an expensive approach. – Solomon Rutzky Jan 23 '15 at 17:54