Alter procedure budgetno_proc
#wono varchar(max),
#retvalue varchar(max) output
as
begin
declare #budno varchar(max)
if not exists(select * from budgetdet where wono=#wono)
begin
set #budno =LEFT(#wono,13)+'-'+RIGHT('0'+CAST((SELECT ISNULL(MAX(CONVERT(INT,LEFT(#wono,13))),0)+1 from budgetdet WHERE wono=#wono) AS VARCHAR(20)),1)
end
else
begin
set #budno=LEFT(#wono,13)+'-'+'1R'+'-'+RIGHT('000'+CAST((SELECT MAX(CONVERT(INT,SUBSTRING(budno,18,LEN(budno))))+1 from budgetdet WHERE wono=#wono) AS VARCHAR(20)),3)
end
set #retvalue = #budno
end
This is my stored procedure with output parameter.
And this is my C# code:
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["gdb"].ConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand("budgetno_proc", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#wono",Workorder_txt.Text);
SqlParameter param = new SqlParameter("#retvalue", SqlDbType.VarChar,30);
param.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add(param);
string budgetnum = (string)cmd.Parameters["#retvalue"].Value;
cmd.ExecuteNonQuery();
con.Close();
I can't get that #retvalue value from the procedure.
Any changes that I have to make? Please note it.
Thanks
You have set the ParameterDirection to Output instead of ReturnValue
param.Direction = ParameterDirection.Output;
cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
string budgetnum = (string)cmd.Parameters["#retvalue"].Value;
Surely you need to swap these lines
cmd.ExecuteNonQuery();
string budgetnum = (string)cmd.Parameters["#retvalue"].Value;
Execute first and then try to read the return value
At first glance, if you want to use ParamDirection.ReturnValue you need to add the RETURN statement as the last line of your SP, but, looking at the page about RETURN statement you will notice this info about the return expression
Is the integer value that is returned. Stored procedures can return an
integer value to a calling procedure or an application.
So you cannot return a string. This leaves only one option.
Using the ParamDirection.Output for the #retvalue parameter instead of the ReturnValue.
Also you have another problem. The size of the parameter cannot be fixed to 30 char if you expect (or declare) an output parameter of VARCHAR(MAX). You need to set the size to -1 on the C# side of your code.
So these lines need to be changed
SqlParameter param = new SqlParameter("#retvalue", SqlDbType.VarChar,-1); //<-Size=-1
param.Direction = ParameterDirection.Output; // <- Output
cmd.Parameters.Add(param);
Related
I am getting this error when I try to call my stored procedure form code behind in my website. I have been stuck for quite a while now, as I do not know anywhere I am converting or declaring a value as an integer. This is my SQL statement:
create procedure GetRepPhoneID
#Rep nvarchar(100),
#phoneID nvarchar(100) output
as
set #phoneID = (select concat(CustomerRepPh, '~', cast(RepID as nvarchar(100))) as 'PhoneAndID'
from Reps
where CustomerRep=#Rep)
return #phoneID
go
Then from my c# code behind I am trying to call the stored procedure:
public static string GetRepPhone(string Rep)
{
string Connection = WebConfigurationManager.ConnectionStrings["JDC_DatabaseConnectionString"].ConnectionString;
SqlConnection sqlConnection = new SqlConnection(Connection);
//This funciton will take all of the values and create them.
try
{
sqlConnection.Open();
}
catch (Exception err)
{
Console.WriteLine(err.Message);
}
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlConnection;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "GetRepPhoneID"; //getting the procedure created in SQL.
SqlParameter CustomerParam = new SqlParameter();
CustomerParam.ParameterName = "Rep";
CustomerParam.SqlDbType = SqlDbType.NVarChar;
CustomerParam.Value = Rep;
CustomerParam.Direction = ParameterDirection.Input;
//We are using an output parameter not a return one because it is a string.
SqlParameter ReturnParam = new SqlParameter("phoneID", SqlDbType.NVarChar, 100);
ReturnParam.Direction = ParameterDirection.Output;
cmd.Parameters.Add(CustomerParam);
cmd.Parameters.Add(ReturnParam);
cmd.ExecuteNonQuery();
sqlConnection.Close();
return ReturnParam.Value.ToString();
}
I am doing the same thing multiple times in my code, but they all return integers so there has been no error thrown so I know it should work. The error is being thrown on the cmd.ExecuteNonQuery() line. The exact error is:
Conversion failed when converting the nvarchar value '(111)222-6666~29' to data type int.
I understand that I cannot convert that string to an integer, but I do not see anywhere in my code I am declaring an integer, or I am trying to convert.
Any help will be appreciated. Thanks.
You are confusing a RETURN value for an OUTPUT parameter. A RETURN is an optional status code of type INT. Declare another parameter as OUTPUT.
Meaning, this is invalid in the Stored Procedure:
return #phoneID
Instead, add #phoneID nvarchar(100) OUTPUT to the parameter list and remove the DECLARE #PhoneID:
CREATE PROCEDURE GetRepPhoneID
(
#Rep NVARCHAR(100),
#phoneID NVARCHAR(100) OUTPUT
)
AS
SET NOCOUNT ON;
SELECT #phoneID = concat(CustomerRepPh, '~', RepID)
FROM Reps
WHERE CustomerRep = #Rep;
The above represents the entire proc. You don't need the RETURN or the SET.
Then in the C# code, you need to change how that parameter is specified:
SqlParameter ReturnParam = new SqlParameter("phoneID", SqlDbType.NVarChar, 100);
ReturnParam.Direction = ParameterDirection.Output;
Then remove this line as it is not needed since the value of the parameter will remain after the connection is closed:
string PhoneAndID = cmd.Parameters[1].Value.ToString();
And change the return to be:
return ReturnParam.Value.ToString();
Lastly, you probably need to update the declaration of the input param as follows:
SqlParameter CustomerParam = new SqlParameter("Rep", SqlDbType.NVarChar, 100);
CustomerParam.Value = Rep;
CustomerParam.Direction = ParameterDirection.Input;
As a part of getting to learn Stored procedures , I came up with this.
CREATE PROCEDURE StoredProcedure1
#oResult int output
AS
BEGIN
SELECT #oResult = 2
RETURN #oResult
END
But the problem is on execution of this SP, it just returns something like.
Procedure or function 'StoredProcedure1' expects parameter '#oResult', which was not supplied.
I want this procedure just to return a result when called.
Any ideas why ?
I supplied as it was asking,EXEC StoredProcedure1 #oResult = 0 but it just says Command Completed Successfully but no output.
Any ideas why ?
In ADO.NET when you call a Stored Procedure that expects a parameter, you need to give that parameter, also if it is an output parameter.
using(SqlConnection cnn = new SqlConnection(.....))
using(SqlCommand cmd = new SqlCommand("StoredProcedure1", cnn))
{
cnn.Open();
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter p = new SqlParameter("#oResult", SqlDbType.Int);
p.Direction = ParameterDirection.Output;
cmd.Parameters.Add(p);
cmd.ExecuteNonQuery();
int result = Convert.ToInt32(cmd.Parameters["#oResult"].Value);
}
Of course, in the stored procedure you should set the #oResult parameter in some way as explained in the other answers, but if you use an OUTPUT parameter there is no need to RETURN the same value.
However you could have both an OUTPUT parameter and a RETURN value if you need to. In this case your call from C# should be
using(SqlConnection cnn = new SqlConnection(.....))
using(SqlCommand cmd = new SqlCommand("StoredProcedure1", cnn))
{
cnn.Open();
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter p = new SqlParameter("#oResult", SqlDbType.Int);
p.Direction = ParameterDirection.Output;
cmd.Parameters.Add(p);
// Here the name #returnValue is arbitrary, you could call it whatever you like
SqlParameter r = new SqlParameter("#returnValue", SqlDbType.Int);
r.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add(r);
cmd.ExecuteNonQuery();
int result = Convert.ToInt32(cmd.Parameters["#oResult"].Value);
int returnValue = Convert.ToInt32(cmd.Parameters["#returnValue"].Value);
}
But keep in mind that RETURN values are limited to Integer Expressions.
You could do this:
Store procedure
CREATE PROCEDURE StoredProcedure1
#oResult int output
AS
BEGIN
SET #oResult = 2
END
And then calling it like this:
DECLARE #Result INT
exec StoredProcedure1 #oResult = #Result output
SELECT #Result
This will output
2
Update:
Like addressed in the comment. You could also simplify the statement. By doing this:
DECLARE #Result INT
exec StoredProcedure1 #Result output
SELECT #Result
Reference:
Execute stored procedure with an Output parameter?
You do not need to write return ..try below code :-
CREATE PROCEDURE StoredProcedure1
#oResult int output
AS
BEGIN
SET #oResult = 2
END
CREATE PROCEDURE SP1
(
#oResult int output
)
AS
BEGIN
SET #oResult=2
Select #oResult
END
I'm using a stored procedure to count and validate if a username already exists in the database, but the problem isn't there, my problem is when I try to obtain the value of the SELECTION in C# in some blogs I found this code:
// Create ConnectionString
string connectionString = ConfigurationManager.ConnectionStrings["ProjectPractice"].ConnectionString;
// Check if the username is not in the DataBase
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmo = new SqlCommand("spBuscaUsuarioMail", con);
cmo.CommandType = CommandType.StoredProcedure;
cmo.Parameters.AddWithValue("#Username", 1);
SqlParameter NroUserName = new SqlParameter("#Num_de_Usuarios", 0);
NroUserName.Direction = ParameterDirection.Output;
cmo.Parameters.Add(NroUserName);
con.Open();
int contarUsername = Int32.Parse(cmo.Parameters["#Num_de_Usuarios"].Value.ToString());
This seems to be great! And it looks like function very well but then in the last part int contarUsername = Int32.Parse... C# gives me an exception that is the next:
NullReferenceException was unhandled by user code.
Object reference not set o an instance of an object.
Then, in troubleshooting tips I read:
Check to determine if the object is null before calling the method.
Use the "new keyword to create an object instance.
Get general help for this exception.
I tried a lot of things, but now I feel really tired and I can't think in a new solution.
This is the stored procedure I'm using:
CREATE PROCEDURE spBuscaUsuarioMail
#Username CHAR (25),
#Num_de_Usuarios INT OUTPUT
AS
BEGIN
SET NOCOUNT ON
SELECT #Num_de_Usuarios = COUNT (UserName)
FROM dbo.Usuarios
WHERE UserName = #Username
END
EXEC spBuscaUsuarioMail '1', #Num_de_Usuarios OUTPUT
SELECT #Num_de_Usuarios
There's something wrong with your parameters....
In the stored procedure, you have
#Username CHAR (25),
#Num_de_Usuarios INT OUTPUT
yet in your C# code, you set up both of them as int, it seems:
cmo.Parameters.AddWithValue("#Username", 1);
SqlParameter NroUserName = new SqlParameter("#Num_de_Usuarios", 0);
NroUserName.Direction = ParameterDirection.Output;
cmo.Parameters.Add(NroUserName);
I think you need to set up the #Username parameter as a string - and give it some meaningful value!
cmo.Parameters.Add("#Username", SqlDbType.Char, 25).Value = "Steve"; // or whatever
And of course, as #Steve already mentioned: you need to actually execute your stored procedure before you can read out the OUTPUT parameter!
If you don't execute the command it is really difficult to get the value of an output parameter
cmo.Parameters.Add(NroUserName);
con.Open();
cmo.ExecuteNonQuery();
int contarUsername = Convert.ToInt32(cmo.Parameters["#Num_de_Usuarios"].Value);
Also the last two lines of the Stored procedure, if they are really in the sp code are meaningless, you don't need them and you get a recursive call on the same stored procedure until somethink breaks . You should remove them
-- remove these two lines
EXEC spBuscaUsuarioMail '1', #Num_de_Usuarios OUTPUT
SELECT #Num_de_Usuarios
Also look at the answer from #marc_s, he points to another problem in your code.
This is the solution. It works!
string connectionString = connectionString = ConfigurationManager.ConnectionStrings["ProjectPractice"].ConnectionString;
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmo = new SqlCommand("spBuscaUsuario", con);
cmo.CommandType = CommandType.StoredProcedure;
cmo.Parameters.Add("#Username", SqlDbType.Char, 25).Value = txtUsername.Text;
SqlParameter NroUserName = new SqlParameter("#Num_de_Usuarios", 0);
NroUserName.Direction = ParameterDirection.Output;
cmo.Parameters.Add(NroUserName);
con.Open();
cmo.ExecuteNonQuery();
int contarUsername = Int32.Parse(cmo.Parameters["#Num_de_Usuarios"].Value.ToString());
And this is the Stored Procedure...
CREATE PROCEDURE spBuscaUsuario
#Username CHAR (25),
#Num_de_Usuarios INT OUTPUT
AS
BEGIN
SET NOCOUNT ON
SELECT #Num_de_Usuarios = COUNT (UserName)
FROM dbo.Usuarios
WHERE UserName = #Username
END
I expect this code be useful for someone else.
I am using a code to call a Stored Procedure having 2 output and 1 input parameter. But i keep getting an error every time I call this stored proc:
CREATE PROCEDURE [dbo].[usp_StoredProcName]
#inputVal nvarchar(255),
#isError bit OUTPUT,
#errorInfo nvarchar(255) OUTPUT
AS BEGIN
DECLARE #totalRow int = 0;
DECLARE #inputValID uniqueidentifier;
SET #isError = 1;
SET #errorInfo = '';
SELECT #inputValID = [inputValID]
FROM testTable
WHERE inputVal = #inputVal;
IF #inputValID IS NULL
BEGIN
SET #isError = 0;
SET #errorInfo = 'inputVal not found';
RETURN
END
END
I have used couple of C# methods to call the stored proc and I get they all return this error:
Procedure or function 'usp_StoredProcName' expects parameter '#inputVal', which was not supplied.
C# Method 1 (to call the stored proc)
using (SqlConnection con = new SqlConnection(myFullConncectionStringToDB))
{
using (SqlCommand cmd = new SqlCommand("usp_StoredProcName", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#inputVal", "MyParamVal_12345");
cmd.Parameters["#isError"].Direction = ParameterDirection.Output;
cmd.Parameters["#errorInfo"].Direction = ParameterDirection.Output;
con.Open();
cmd.ExecuteNonQuery();
var isError = cmd.Parameters["#isError"].Value;
var errInfo = cmd.Parameters["#errorInfo"].Value;
con.Close();
}
}
Method 2 ( to call the stored proc)
SqlConnection con = new SqlConnection(myFullConncectionStringToDB);
SqlCommand cmd = new SqlCommand("usp_StoredProcName", con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter in_parm = new SqlParameter("#inputVal", SqlDbType.NVarChar);
in_parm.Size = 255;
in_parm.Value = "MyParamVal_12345";
in_parm.Direction = ParameterDirection.Input;
cmd.Parameters.Add(in_parm);
SqlParameter out_parm = new SqlParameter("#errorInfo", SqlDbType.NVarChar);
out_parm.Size = 255;
out_parm.Direction = ParameterDirection.Output;
cmd.Parameters.Add(out_parm);
SqlParameter out_parm1 = new SqlParameter("#isError", SqlDbType.Bit);
out_parm1.Direction = ParameterDirection.Output;
cmd.Parameters.Add(out_parm1);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
Both of the above methods I tried return the same error:
Procedure or function 'usp_StoredProcName' expects parameter '#inputVal', which was not supplied.
Please tell me what am I doing wrong here in my C# code to execute the stored procedure.
I am clearly passing the parameter value in both of my methods but can't figure out why I keep getting this error.
Thank you for your help.
I usually break down the solution into pieces an make sure each one works.
First, test the Stored Procedure to make sure it works as planned. Sample call is below.
-- Switch to your database
USE [YourDatabase]
GO
-- Declare output variables
DECLARE #out_is_error bit;
DECLARE #out_error_info nvarchar(255);
-- Execute sp
EXECUTE [dbo].[usp_StoredProcName]
N'In Data',
#isError = #out_is_error OUTPUT,
#errorInfo = #out_error_info OUTPUT;
-- Show any SQL errors / return data
PRINT ##ERROR;
PRINT 'Error = ' + #out_error_info;
PRINT 'Flag = ';
PRINT CAST(#out_is_error as CHAR(1));
GO
Next, look at the C# piece of the puzzle. Aaron suggestion about correct database is a good one. Do you have two copies of the SP floating around?
Good luck.
I'm trying to retrieve the return value of a stored procedure in SQL Server 2005 as follows:
OleDbCommand comm = new OleDbCommand(process_name, connection);
comm.CommandType = CommandType.StoredProcedure;
for (int i = 0; i < process_parameters.Length; i++)
comm.Parameters.AddWithValue(process_parameters[i].ParameterName, process_parameters[i].Value);
//Add output param
comm.Parameters.Add("#TestID", OleDbType.Integer).Direction = ParameterDirection.ReturnValue;
comm.ExecuteNonQuery();
When ExecuteNonQuery() is called, however, I get back a OleDbException saying: "Procedure or function myStoredProcedure has too many arguments specified." My stored procedure begins as follows:
ALTER PROCEDURE [dbo].[spTabtempTestsINSERT]
(
#Param1 char (64),
#Param2 char (128),
#Param3 char (64),
)
AS
BEGIN
Declare #TestID int
And ends with the following:
RETURN #TestID
END
Does the fact that the return value is declared, rather than being passed as a parameter, have anything to do with it? If so, how can I get the return value of a param that's declared after the stored procedure begins? Thanks for your help.
UPDATE:
I've tried the changes suggested so far, I added the following line:
OleDbCommand comm = new OleDbCommand(process_name, connection);
comm.CommandType = CommandType.StoredProcedure;
for (int i = 0; i < process_parameters.Length; i++)
comm.Parameters.AddWithValue(process_parameters[i].ParameterName, process_parameters[i].Value);
var testID = (int)comm.ExecuteScalar();
Now when ExecuteScalar() gets executed, I get a NullReferenceException with Object reference not set to an instance of an object.
Note: I also tried setting it to an integer int testID = (int)comm.ExecuteScalar(); and I still get the same error.
Change
comm.ExecuteNonQuery();
to
int returnValue = (int) comm.ExecuteScalar();
And remove:
comm.Parameters.Add("#TestID", OleDbType.Integer).Direction = ParameterDirection.ReturnValue;
I thought ExecuteNonQuery() doesn't return anything from SQL..... am I missing something here?
remove these:
//Add output param
comm.Parameters.Add("#TestID", OleDbType.Integer).Direction = ParameterDirection.ReturnValue;
comm.ExecuteNonQuery();
and use this instead: var testID = (int) comm.ExecuteScalar();
Ok, I was able to get it to work properly. My problem was that, I neglected to declare any of the parameters as OUTPUT, I added an extra variable and set that as the output variable and had the stored procedure return that. After word I just checked that output parameter ,after calling the stored procedure, from my C# code, the following shows the changes:
ALTER PROCEDURE [dbo].[spTabtempTestsINSERT]
(
#Param1 char (64),
#Param2 char (128),
#Param3 char (64),
#ReturnValue int OUTPUT
)
AS
BEGIN
Declare #TestID int
And at the end make a simple change:
SET #ReturnValue = #TestID
RETURN #ReturnValue
END
Finally, back in my code:
OleDbCommand comm = new OleDbCommand(process_name, connection);
comm.CommandType = CommandType.StoredProcedure;
for (int i = 0; i < process_parameters.Length; i++)
comm.Parameters.AddWithValue(process_parameters[i].ParameterName, process_parameters[i].Value);
//Add output param
comm.Parameters.Add("#ReturnValue", OleDbType.Integer).Direction = ParameterDirection.ReturnValue;
comm.ExecuteNonQuery();
Console.WriteLine("Stored Procedure returned a value of "+ comm.Parameters["#ReturnValue"].Value); //Success
Thank you all for your suggestions. Any alternatives or further insights are welcome.
In response to the accepted answer...
Because you are setting the parameter's Direction to ReturnValue here:
comm.Parameters.Add("#ReturnValue", OleDbType.Integer).Direction = ParameterDirection.ReturnValue;
You don't need an OUTPUT parameter in your stored procedure at all. You could change it back to:
ALTER PROCEDURE [dbo].[spTabtempTestsINSERT]
(
#Param1 char (64),
#Param2 char (128),
#Param3 char (64),
)
AS
BEGIN
Declare #TestID int
With:
RETURN #TestID
END
at the end and it would still work exactly as it does now.
It is purely coincidental that your ReturnValue Parameter in C# bears the same name as your OUTPUT parameter. There is a separate parameter Direction for OUTPUT parameters.
I had the same issue, the problem is that you have to declare the return parameter first (before the input and output ones), this way it works:
OleDbCommand comm = new OleDbCommand(process_name, connection);
comm.CommandType = CommandType.StoredProcedure;
//Add the return param first
comm.Parameters.Add("#TestID", OleDbType.Integer).Direction = ParameterDirection.ReturnValue;
for (int i = 0; i < process_parameters.Length; i++)
comm.Parameters.AddWithValue(process_parameters[i].ParameterName, process_parameters[i].Value);
comm.ExecuteNonQuery();
Object return_value = comm.Parameters["#TestID"].Value;