SQL Server 存储过程执行更新操作后,如何知道是否成功?

3

假设我有一个存储过程,但我无法控制它(也无法访问第三方数据库)。

那么,我如何知道它是否运行成功?

BEGIN
        Update USR
        Set usr_psswrd = @NewPassword
        where
            usr_usrnme = @UserName and usr_psswrd = @OldPassword
END

我知道如何在存储过程中使用select语句获取行并读取这些行,但我不知道如何检查此存储过程是否成功。

到目前为止,我所做的事情是不起作用的。存储过程有效,因为密码确实更改了,但事后我不知道该怎么做。

using (SqlConnection connection = new SqlConnection(connectionString))
{
            // Create the command and set its properties.
            SqlCommand command = new SqlCommand();
            command.Connection = connection;
            command.CommandText = "USP_ChangePassword";
            command.CommandType = CommandType.StoredProcedure;

            command.Parameters.Add("@UserName", SqlDbType.VarChar).Value = email;
            command.Parameters.Add("@OldPassword", SqlDbType.VarChar).Value = oldPW;
            command.Parameters.Add("@NewPassword", SqlDbType.VarChar).Value = newPW;

            try
            {
                // Open the connection and execute the reader.
                connection.Open();
                command.ExecuteNonQuery();

                SqlDataReader reader = command.ExecuteReader();

                if (reader.HasRows)
                {
                    success = true;
                }

                reader.Close();

            }
            catch (SqlException ex)
            {
                System.Diagnostics.Debug.Write("SqlException Error " + ex.Number + ": " + ex.Message);
            }
            catch (InvalidOperationException ex)
            {
                System.Diagnostics.Debug.Write("Invalid Op Error: " + ex.Message);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.Write("Error: " + ex.Message);
            }
            finally
            {
                connection.Close();
            }
}

我建议你摆脱那些try/catch块,或者最坏的情况下,做 catch (Exception ex){System.Diagnostics.Debug.Write("Error: " + ex.ToString());throw;} 此外,你的 SqlCommandSqlDataReader 需要在 using 块中。 - John Saunders
2个回答

7

在有关ExecuteNonQuery的文档中,您可以找到以下内容:

> Return Value 
> Type: System.Int32 
> The number of rows affected.

所以您可以将您的代码更改为


try
{
    // Open the connection and execute the reader.
    connection.Open();
    int rowsUpdated = command.ExecuteNonQuery();
    if(rowsUpdated > 0)
    {
        success = true;
    }
}

这是ExecuteNonQuery的正常行为,但请检查您的存储过程是否包含这些语句。
SET NOCOUNT ON

如果你有这行代码,那么ExecuteNonQuery无法返回受影响的行数,你总是会得到一个-1作为返回值。如果你无法更改存储过程,那么你就有麻烦了。
唯一想到的解决方法是使用SELECT查询获取用户数据,并检查插入的数据(非常不方便)。

3
如果您查看ExecuteNonQuery()方法的文档,您将看到它返回一个int,具体如下:

对于UPDATE、INSERT和DELETE语句,返回值是命令影响的行数。当存在于插入或更新操作的表上的触发器时,返回值包括由插入或更新操作以及触发器或触发器所影响的行数。对于所有其他类型的语句,返回值为-1。如果发生回滚,则返回值也为-1。

因此,如果您执行该方法调用并返回1,则可以安全地假设您的字段已成功更新。 这意味着您应该删除SqlDataReader reader = command.ExecuteReader();行,并添加一个返回值检查,例如:
var success = command.ExecuteNonQuery() == 1; 

(这是一种简洁的方式,你可以将其拆分成多行。)

== 1 还是 == -1?这里没有提到值等于1的情况。 - VSB
1
@VSB 你的评论对我来说没有太多意义。 OP 正在尝试更新一行。 这就是为什么我建议检查返回值 1 的原因。 - slugster
当出现像CREATE TABLE或创建外键关系这样的情况时,您知道我们应该期望什么样的返回值吗? - VSB
@VSB 我相信上面的引用已经涵盖了这个问题:“……对于所有其他类型的语句……” - slugster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接