Good morning everyone,
The short and sweet question is: what will SqlCommand.ExecuteNonQuery() return in the case of the query being multiple drop table statements?
For example, if I pass five tables to my drop method, and it builds a query with five drop table statements, what will ExecuteNonQuery return? I think it will return a value of negative one (based on MSDN), hoping it will return the exact count of tables that were dropped successfully, and hoping that it will not return the number of rows cumulatively removed from the database since this would be extremely excessive and most likely not the answer.
CODE
string query = string.Empty;
foreach (string name in tableNames)
query += $"DROP TABLE [{name}]; ";
using (SqlCommand cmd = new SqlCommand(query, conn)
droppedTableCount = cmd.ExecuteNonQuery(); // Returns number of rows affected.
return droppedTableCount;
MSDN
You can use the ExecuteNonQuery to perform catalog operations (for example, querying the structure of a database or creating database objects such as tables), or to change the data in a database without using a DataSet by executing UPDATE, INSERT, or DELETE statements. Although the ExecuteNonQuery returns no rows, any output parameters or return values mapped to parameters are populated with data. For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers. For all other types of statements, the return value is -1. If a rollback occurs, the return value is also -1.
Related
I'm trying to search a sql table for a specific string, and return the number of observations found. It keeps returning -1 though, whether the string is in the table or not. Here's my code:
#{
Layout = "~/_Layout.cshtml";
Page.title = "TestArea";
var db = Database.Open("Cafeen");
string SearchWord = "Jolly";
var msg = db.Execute("SELECT COUNT(*) FROM Products WHERE ProductName = #SearchWord");
}
<p>#msg</p>
Should I perhaps use something other than COUNT(*)? What is the significance of -1? I would have assumed the expression to return 0 if the string can't be found.
You are using the WebMatrix.Data namespace. In this context you should call the QuerySingle method not the Execute one because, as many have already stated, that method is for not returning rows data.
The Execute method is used to perform non-query commands on a
database, such as the SQL Drop, Create, Delete, Update, and Insert
commands.
Moreover I suggest to change your query statement to a more performant one
var db = Database.Open("Cafeen");
string SearchWord = "Jolly";
string cmdText = #"IF EXISTS(SELECT 1 FROM Products
WHERE ProductName = #searchWord)
SELECT 1 ELSE SELECT 0";
int exists = Convert.ToInt32(db.QuerySingle(cmdText, SearchWord));
.....
Pertinent to the SQL Database, there is:
SqlCommand.ExecuteScalar Method ()
(re: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar(v=vs.110).aspx)
Otherwise, refer to Database.QueryValue Method (re: https://msdn.microsoft.com/en-us/library/webmatrix.data.database.queryvalue(v=vs.111).aspx)
Both methods return a scalar value from the first column/ first row.
Also, instead of COUNT(*) in SQL statement you can use COUNT(1) for better performance.
Hope this may help.
In db.Execute and SqlCommand.ExecuteNonQuery:
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers. For all other types of statements like SELECT, the return value is -1. If a rollback occurs, the return value is also -1.
Have a look at the following links may be helpful:
https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executenonquery.aspx
How to Identify whether SQL job is successfully executed or not in C#
I've been searching for a way to get information about a completed SQL transaction. Since I'm using C# to connect to a DB I want to know how many records were updated, inserted or deleted during a specific transaction.
Is there any way to do this?
Thanks in advance
ExecuteNonQuery() returns the number of rows affected.
SqlCommand command = new SqlCommand(queryString, connection);
command.Connection.Open();
int rowsAffected = command.ExecuteNonQuery();
If you want multiple records, i.e. the total number of records deleted, inserted, updated etc. You would have to use an OUTPUT parameter.
command.Parameters.Add("#DeletedRecords", SqlDbType.Int);
command.Parameters["#DeletedRecords"].Direction = ParameterDirection.Output;
Then in your transactional stored procedure:
CREATE PROCEDURE [dbo].[TransactionReportStatus]
#DeletedRecords INT OUTPUT
AS
BEGIN
-- Your transaction with delete statements
SET #DeletedRecords = ##ROWCOUNT
END
##ROWCOUNT is SQL Server's equivalent of ExecuteNonQuery()
Note that in sql server rows affected for an update statement tells you how many rows meet the selection criteria, not the count of rows that were actually changed in contrast to mysql which returns the number of rows that were actually changed. I prefer to know the number of rows actually changed. If there is a way to do that in sql server, I would like to know how.
We are refactoring a project from plain MySQL queries to the usage of NHibernate.
In the MySQL connector there is the ExecuteNonQuery function that returns the rows affected. So
int RowsDeleted = ExecuteNonQuery("DELETE FROM `table` WHERE ...");
would show me how many rows where effectively deleted.
How can I achieve the same with NHibernate? So far I can see it is not possible with Session.Delete(query);.
My current workaround is first loading all of the objects that are about to be deleted and delete them one-by-one, incrementing a counter on each delete. But that will cost performance I may assume.
If you don't mind that nHibernate will create delete statements for each row and maybe additional statements for orphans and/or other relationships, you can use session.Delete.
For better performance I would recommend to do batch deletes (see example below).
session.Delete
If you delete many objects with session.Delete, nHibernate makes sure that the integrity is preserved, it will load everything into the session if needed anyways. So there is no real reason to count your objects or have a method to retrieve the number of objects which have been deleted, because you would simply do a query before running the delete to determine the number of objects which will be affected...
The following statement will delete all entities of type post by id.
The select statement will query the database only for the Ids so it is actually very performant...
var idList = session.Query<Post>().Select(p => p.Id).ToList<int>();
session.Delete(string.Format("from Post where Id in ({0})", string.Join(",", idList.ToArray())));
The number of objects deleted will be equal to the number of Ids in the list...
This is actually the same (in terms of queries nHibernate will fire against your database) as if you would query<T> and loop over the result and delete all of them one by one...
Batch delete
You can use session.CreateSqlQuery to run native SQL commands. It also allows you to have input and output parameters.
The following statement would simply delete everything from the table as you would expect
session.CreateSQLQuery(#"Delete from MyTableName");
To retrieve the number of rows delete, we'll use the normal TSQL ##ROWCOUNT variable and output it via select. To retrieve the selected row count, we have to add an output parameter to the created query via AddScalar and UniqueResult simple returns the integer:
var rowsAffected = session.CreateSQLQuery(#"
Delete from MyTableName;
Select ##ROWCOUNT as NumberOfRows")
.AddScalar("NumberOfRows", NHibernateUtil.Int32)
.UniqueResult();
To pass input variables you can do this with .SetParameter(<name>,<value>)
var rowsAffected = session.CreateSQLQuery(#"
DELETE from MyTableName where ColumnName = :val;
select ##ROWCOUNT NumberOfRows;")
.AddScalar("NumberOfRows", NHibernateUtil.Int32)
.SetParameter("val", 1)
.UniqueResult();
I'm not so confortable with MySQL, the example I wrote is for MSSQL, I think in MySQL the ##ROWCOUNT equivalent would be SELECT ROW_COUNT();?
How can i know if i create a database successfully? I am using "CREATE DATABASE DemoDB" as a SQL command. ExecuteNonQuery() method returns 0. What should i use to understand if i created a database successfully?
As MSDN says:
For UPDATE, INSERT, and DELETE statements, the return value is the
number of rows affected by the command. When a trigger exists on a
table being inserted or updated, the return value includes the number
of rows affected by both the insert or update operation and the number
of rows affected by the trigger or triggers. For all other types of
statements, the return value is -1. If a rollback occurs, the return
value is also -1.
ExecuteNonQuery will return 0 for a CREATE DATABASE command because it returns the rows changed by your query.
This will return some rows if the DB exists:
SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'DemoDB'
ExecuteNonQuery throws a MySqlException exception if there is an error. It returns 0 if successful but you don't need to check the return value; if it returns normally it has succeeded. For example here is the exception I get when I try to create a database that already exists:
Can't create database 'name'; database exists
This is my (rough) code (DAL):
int i;
// Some other declarations
SqlCommand myCmdObject = new SqlCommand("some query");
conn.open();
i = myCmdObject.ExecuteNonQuery();
conn.close();
The problem is: Even though there is a record present on my SELECT query, the value in i remains -1.
What could be the problem?
What kind of query do you perform? Using ExecuteNonQuery is intended for UPDATE, INSERT and DELETE queries. As per the documentation:
For UPDATE, INSERT, and DELETE
statements, the return value is the
number of rows affected by the
command. When a trigger exists on a
table being inserted or updated, the
return value includes the number of
rows affected by both the insert or
update operation and the number of
rows affected by the trigger or
triggers. For all other types of
statements, the return value is -1.
Whenever you want to execute an SQL statement that shouldn't return a value or a record set, the ExecuteNonQuery should be used.
So if you want to run an update, delete, or insert statement, you should use the ExecuteNonQuery. ExecuteNonQuery returns the number of rows affected by the statement. This sounds very nice, but whenever you use the SQL Server 2005 IDE or Visual Studio to create a stored procedure it adds a small line that ruins everything.
That line is: SET NOCOUNT ON; This line turns on the NOCOUNT feature of SQL Server, which "Stops the message indicating the number of rows affected by a Transact-SQL statement from being returned as part of the results" and therefore it makes the stored procedure always to return -1 when called from the application (in my case a web application).
In conclusion, remove that line from your stored procedure, and you will now get a value indicating the number of rows affected by the statement.
Happy programming!
http://aspsoft.blogs.com/jonas/2006/10/executenonquery.html
You use EXECUTENONQUERY() for INSERT,UPDATE and DELETE.
But for SELECT you must use EXECUTEREADER().........
Because the SET NOCOUNT option is set to on. Remove the line "SET NOCOUNT ON;" in your query or stored procedure.
See more at SqlCommand.ExecuteNonQuery() returns -1 when doing Insert / Update / Delete.
Could you post the exact query? The ExecuteNonQuery method returns the ##ROWCOUNT Sql Server variable what ever it is after the last query has executed is what the ExecuteNonQuery method returns.
The ExecuteNonQuery method is used for SQL statements that are not queries, such as INSERT, UPDATE, ... You want to use ExecuteScalar or ExecuteReader if you expect your statement to return results (i.e. a query).
From MSDN: SqlCommand.ExecuteNonQuery Method
You can use the ExecuteNonQuery to
perform catalog operations (for
example, querying the structure of a
database or creating database objects
such as tables), or to change the data
in a database without using a DataSet
by executing UPDATE, INSERT, or DELETE
statements.
Although the ExecuteNonQuery returns
no rows, any output parameters or
return values mapped to parameters are
populated with data.
For UPDATE, INSERT, and DELETE
statements, the return value is the
number of rows affected by the
command. When a trigger exists on a
table being inserted or updated, the
return value includes the number of
rows affected by both the insert or
update operation and the number of
rows affected by the trigger or
triggers. For all other types of
statements, the return value is -1. If
a rollback occurs, the return value is
also -1.
You are using SELECT query, thus you get -1
If what you want is to get just a single integer from the query, use:
myCmdObject.ExecuteScalar()
if you want to run an update, delete,
or insert statement, you should use
the ExecuteNonQuery. ExecuteNonQuery
returns the number of rows affected by
the statement.
How to Set Count On