2012-10-17 28 views
10

Tôi đang cố thực thi thủ tục lưu sẵn trong Visual Studio. Nó được đưa ra dưới đây.ExecuteNonQuery() trả về -1 khi thực hiện thủ tục đã lưu

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 

Làm như vậy bằng cách sử dụng mã bên dưới.

 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()); 

Nhưng nó trả về tôi -1. Tôi đã thử thủ tục được lưu trữ này bằng cách nhập các giá trị giống như tôi đã chụp từ gỡ lỗi. Nó đã thành công. Lỗi có thể là gì? Cảm ơn rất nhiều!

+0

Thay vì sử dụng dòng 'SET @currentID = (SELECT MAX)', hãy thử sử dụng '@@ IDENTITY'. Không liên quan đến lỗi, nhưng chỉ là một mẹo. – SchmitzIT

+0

Bạn thực sự nên sử dụng định dạng 'yyyyMMdd' cho các ngày chứ không phải định dạng' MM-dd-yyyy' hoặc các định dạng tương tự, nó có nhiều nền văn hóa bất khả tri hơn theo cách đó. – Seph

+0

@Seph - chúng phải truyền chúng như 'DateTime' và không định dạng chúng thành chuỗi. –

Trả lời

14

Không sử dụng = null, sử dụng is null

IF @existPerson is null 

Khi bạn so sánh bất cứ điều gì = null kết quả là luôn luôn sai (trừ khi bạn có set ansi_nulls off, mà bạn không nên, như một tùy chọn như bị phản đối)

Thậm chí tốt hơn, bạn có thể sử dụng

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

Ngoài ra, bạn nên sử dụng SCOPE_IDENTITY() thay vì SET @currentID = (SELECT MAX(p_ID) FROM Person);

SET @currentID = SCOPE_IDENTITY() 

Cuối cùng bạn cũng cần phải thêm một tham số để thu thập các giá trị trả về

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

sau đó

MessageBox.Show(retValue.Value); 
+0

Cảm ơn rất nhiều.Câu trả lời này đã giúp tôi rất nhiều! – don

11

Hãy có một cái nhìn tại tài liệu cho ExecuteNonQuery :

Đối với các câu lệnh UPDATE, INSERT và DELETE, giá trị trả về là số hàng bị ảnh hưởng bởi lệnh. ... Đối với tất cả các loại câu lệnh khác, giá trị trả về là -1.

Bạn đang gọi quy trình được lưu trữ, trong đó, và không phải là một trong 3 câu lệnh được liệt kê trong đó đếm số hàng.


Nếu bạn muốn xác định các giá trị đã được thông qua một tuyên bố return trong thủ tục lưu trữ, bạn cần phải thêm tham số khác cho lệnh, và thiết lập thuộc tính Direction của nó để ReturnValue (tên mà bạn cung cấp cho này tham số sẽ bị bỏ qua)

+3

Điều này là sai, nếu thủ tục được lưu trữ đang thực hiện Cập nhật, Chèn hoặc Xóa nó sẽ trả về số hàng bị ảnh hưởng bởi lệnh này nếu nó được gọi bởi ExecuteNonQuery. Một thủ tục lưu sẵn trong trường hợp này không được coi là một câu lệnh, các câu lệnh bên trong thủ tục lưu sẵn là. –

+1

SO sẽ không cho phép tôi loại bỏ upvote của tôi vì vậy tôi đang bình luận - câu trả lời này là sai. Lý do tôi nghĩ nó là chính xác là vì tôi đã "SET NOCOUNT ON" trong thủ tục lưu trữ của tôi. Nhưng khi tôi sử dụng "SET NOCOUNT OFF" như câu trả lời của @ Ahitosh thì 'ExecuteNonQuery()' trả về đúng số lượng các hàng bị ảnh hưởng được cập nhật trong thủ tục lưu sẵn của tôi. – mulllhausen

+0

Câu trả lời đúng. Nhưng không cần phải có ý nghĩa về nó. Tôi có thể thấy nó có thể gây nhầm lẫn như thế nào. Hãy nói rằng tôi có một thủ tục lưu trữ mà thực hiện một trong những hoạt động và không có gì khác? Tôi có thể dễ dàng thấy cách mà có thể bị nhầm lẫn là "lỗi". – pimbrouwers

6

Để khắc phục sự cố này, chỉ cần xóa "SET NOCOUNT ON" hoặc Thay đổi thành "SET NOCOUNT OFF". và mọi thứ hoạt động tốt!

+0

Điều này là chính xác. – mulllhausen

Các vấn đề liên quan