2012-10-17 18 views
10

Próbuję wykonać procedura składowana w programie Visual Studio. Jest podana poniżej.ExecuteNonQuery() zwraca -1 podczas wykonywania procedury przechowywanej

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 

Im robi to za pomocą tego kodu poniżej.

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

Ale zwraca mi -1. Próbowałem tej procedury przechowywanej, wprowadzając te same wartości, które przechwyciłem podczas debugowania. To się udało. Jaki może być możliwy błąd? Wielkie dzięki!

+0

Zamiast używać linii 'SET @currentID = (SELECT MAX)', spróbuj użyć '@@ IDENTITY'. Nie związane z błędem, ale tylko wskazówka. – SchmitzIT

+0

Powinieneś używać formatu 'yyyyMMdd' dla dat, a nie' MM-dd-rrrr' lub podobnych formatów, w ten sposób jest o wiele bardziej agnostyczny. – Seph

+0

@Seph - powinny przekazywać je jako 'DateTime's i nie formatować ich w ogóle. –

Odpowiedz

14

Nie używaj = null użyć is null

IF @existPerson is null 

Jeśli porównać niczego = null wynik jest zawsze fałszywe (chyba że masz set ansi_nulls off, który nie należy, jako taka opcja jest przestarzała)

Jeszcze lepiej, można użyć

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

Ponadto, należy użyć SCOPE_IDENTITY() zamiast SET @currentID = (SELECT MAX(p_ID) FROM Person);

SET @currentID = SCOPE_IDENTITY() 

Wreszcie trzeba także dodać parametr do zbierania wartości zwracanej

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

następnie

MessageBox.Show(retValue.Value); 
+0

Wielkie dzięki.Ta odpowiedź bardzo mi pomogła! – don

11

Rzućmy okiem na dokumentacjidla ExecuteNonQuery :

Dla instrukcji UPDATE, INSERT i DELETE zwracana jest liczba wierszy, których dotyczy polecenie. ... Dla wszystkich innych typów instrukcji zwracana jest wartość -1.

Wywołuje procedura składowana, która sama w sobie nie jest z 3 wymienionych instrukcji, gdy liczba wierszy jest zwracana.


Jeśli chcesz określić wartość, która została przekazana do return oświadczenia w ramach procedury przechowywanej, trzeba dodać kolejny parametr do komendy, i ustawić jej Direction właściwość ReturnValue (nazwę oceniasz to parametr zostanie zignorowany)

+3

Jest to niepoprawne, jeśli procedura składowana wykonuje aktualizację, Wstaw lub Usuń zwróci liczbę wierszy, których dotyczy to polecenie, jeśli jest wywoływana przez ExecuteNonQuery. Procedura składowana w tym przypadku nie jest uważana za instrukcję, instrukcje wewnątrz procedury składowanej są. –

+1

SO nie pozwoli mi usunąć mojego wystąpienia, więc komentuję - ta odpowiedź jest błędna. Powodem, dla którego pomyślałem, że to było poprawne było to, że miałem "ZAKŁADANIE NOCOUNT ON" w mojej procedurze przechowywanej. Ale kiedy użyłem "SET NOCOUNT OFF" jako odpowiedź @ Ahitosha, to znaczy, że 'ExecuteNonQuery()' poprawnie zwraca liczbę zmienionych wierszy zaktualizowanych w mojej procedurze przechowywanej. – mulllhausen

+0

Właściwa odpowiedź. Ale nie musicie o tym myśleć. Widzę, jak to może być mylące. Powiedzmy, że mam procedurę przechowywaną, która wykonuje jedną z tych operacji i nic więcej? Mogę z łatwością zobaczyć, jak można go pomylić z "błędem". – pimbrouwers

6

Aby rozwiązać ten problem, po prostu usuń "USTAW NOCOUNT WŁ." lub zmień na "USTAW NOCOUNT WYŁ". i wszystko działa dobrze!

+0

To jest poprawne. – mulllhausen

Powiązane problemy