2012-10-17 50 views
10

我试图在Visual Studio中执行存储过程。它在下面给出。ExecuteNonQuery()在执行存储过程时返回-1

CREATE PROCEDURE [dbo].[addStudent] 
    @stuName varchar(50), 
    @address varchar(100), 
    @tel varchar(15), 
    @etel varchar(15), 
    @nic varchar (10), 
    @dob date 


AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @currentID INT 
    DECLARE @existPerson INT 
    SET @existPerson = (SELECT p_ID FROM Student WHERE s_NIC = @nic); 
    IF @existPerson = null 
     BEGIN 
      INSERT INTO Person (p_Name, p_RegDate, p_Address, p_Tel, p_EmergeNo, p_Valid, p_Userlevel) 
      VALUES (@stuName, GETDATE(), @address, @tel, @etel, 0, 'Student'); 
      SET @currentID = (SELECT MAX(p_ID) FROM Person); 
      INSERT INTO Student (p_ID, s_Barcode, s_DOB, s_NIC) VALUES (@currentID , NULL, @dob, @nic); 
      return 0; 
     END 
    ELSE 
     return -1; 
END 

我正在使用以下代码。

 SqlConnection con = new SqlConnection(); 
     Connect conn = new Connect(); 
     con = conn.getConnected(); 
     con.Open(); 
     cmd = new SqlCommand("addStudent", con); 
     cmd.CommandType = CommandType.StoredProcedure; 
       cmd.Parameters.Add("@stuName", SqlDbType.VarChar).Value = nameTxt.Text.ToString(); 
       cmd.Parameters.Add("@address", SqlDbType.VarChar).Value = addressTxt.Text.ToString(); 
       cmd.Parameters.Add("@tel", SqlDbType.VarChar).Value = telTxt.Text.ToString(); 
       cmd.Parameters.Add("@etel", SqlDbType.VarChar).Value = emerTxt.Text.ToString(); 
       cmd.Parameters.Add("@nic", SqlDbType.VarChar).Value = nicTxt.Text.ToString(); 
       cmd.Parameters.Add("@dob", SqlDbType.DateTime).Value = dobTime.Value.ToString("MM-dd-yyyy"); 

        int n = cmd.ExecuteNonQuery(); 
        MessageBox.Show(n.ToString()); 

但它返回我-1。我通过输入从调试中捕获的相同值来试用此存储过程。它成功了。什么可能是可能的错误? 非常感谢!

+0

而不是使用'SET @currentID =(SELECT MAX)'行,请尝试使用'@@ IDENTITY'。与错误无关,但只是一个提示。 – SchmitzIT

+0

对于日期而言,您应该真的使用'yyyyMMdd'格式,而不是'MM-dd-yyyy'或类似的格式,这种方式对文化更为不可知。 – Seph

+0

@Seph - 他们应该将它们作为DateTime传递,而不是将它们格式化为字符串。 –

回答

14

不要使用= null,使用is null

IF @existPerson is null 

当你比较什么= null结果始终是假的(除非你有set ansi_nulls off,你不应该,因为这样的选项不建议使用)

更妙的是,你可以使用

IF NOT EXISTS (SELECT p_ID FROM Student WHERE s_NIC = @nic) 

此外,你应该使用SCOPE_IDENTITY()代替SET @currentID = (SELECT MAX(p_ID) FROM Person);

SET @currentID = SCOPE_IDENTITY() 

最后,您还需要添加一个参数来收集返回值

SqlParameter retValue = cmd.Parameters.Add("return", SqlDbType.Int); 
    retValue.Direction = ParameterDirection.ReturnValue; 

然后

MessageBox.Show(retValue.Value); 
+0

非常感谢。这个答案帮了我很多! – don

11

让我们来看看文档ExecuteNonQuery

对于UPDATE,INSERT和DELETE语句,返回值是受命令影响的行数。 ... 对于所有其他类型的语句,返回值为-1。

你调用一个存储过程,这在和它本身的,是这里没有返回行数的3个所列的语句。


如果要确定传递给一个return语句存储过程中的值,就需要另一个参数添加到命令,其Direction属性设置为ReturnValue(你给这个名字参数将被忽略)

+3

这是错误的,如果存储过程正在执行更新,插入或删除,它将返回受此命令影响的行数(如果由ExecuteNonQuery调用)。在这种情况下存储过程不被视为一个语句,存储过程中的语句是。 –

+1

SO不会让我删除我的upvote,所以我评论 - 这个答案是错误的。我认为这是正确的原因是因为我在存储过程中“SET NOCOUNT ON”。但是,当我使用“SET NOCOUNT OFF”作为@ Ahitosh的回答时,ExecuteNonQuery()正确返回在我的存储过程中更新的受​​影响行的数量。 – mulllhausen

+0

正确答案。但不一定要这么做。我可以看到它可能会令人困惑。比方说,我有一个存储过程执行这些操作之一,而不是别的?我可以很容易地看到这可能被误认为是一个“bug”。 – pimbrouwers

6

要解决此问题,只需删除“SET NOCOUNT ON”或将其更改为“SET NOCOUNT OFF”。一切正常!

+0

这是正确的。 – mulllhausen