Execute a Query After Call a stored procedure - c#

This is my stored procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_CPC`(
IN _B VARCHAR(100),
IN _G VARCHAR(2),
IN _R VARCHAR(30),
IN _D VARCHAR(30),
OUT _C FLOAT,
OUT _P FLOAT)
BEGIN
//Something Hear
END$$
DELIMITER ;
I Call this stored procedure by C# flowing Code
DataSet tmpDataSet = new DataSet();
mCommand.CommandText = "sp_CPC";
mCommand.CommandType = CommandType.StoredProcedure;
// mCommand.CommandText = "sp_select_all_employees";
mCommand.Parameters.AddWithValue("#_B", "bty-23");
mCommand.Parameters.AddWithValue("#_G", "3");
mCommand.Parameters.AddWithValue("#_R", "9000");
mCommand.Parameters.AddWithValue("#_D", "92");
mCommand.Parameters.Add("#_C",MySqlDbType.Float);
mCommand.Parameters["#_C"].Direction = ParameterDirection.Output;
mCommand.Parameters.Add("#_P", MySqlDbType.Float);
mCommand.Parameters["#_P"].Direction = ParameterDirection.Output;
try
{
mConnection.Open();
mCommand.ExecuteNonQuery();
mAdapter.Fill(tmpDataSet)
}
catch (Exception ex)
{
strErrorInfo = ex.ToString();
}
finally
{
mConnection.Close();
}
DataTable dtb = tmpDataSet.Tables[0];
mCommand.CommandText = "INSERT INTO abc (xxxx,yyyy) VALUES ('" + dtb.Rows[0][0] + "','" + dtb.Rows[0][1] + "')";
mConnection.Open();
mCommand.ExecuteNonQuery();
mConnection.Close();
return tmpDataSet;
it show error in this command mCommand.ExecuteNonQuery();
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-14' AND name LIKE '5378377032052','6'' at line 1.
(Return tmpDataSet) use Because of this data i also use anouther work

The way you construct the INSERT statement is unsafe. You concatenate strings that might contain ' characters, so that your INSERT statement becomes invalid - and also prone to SQL injection attacks. The error message you show in the comments points in this direction.
In order to solve this, use parameters in the INSERT statement as you did in your stored procedure.
Sample:
// ...
mCommand.CommandText = "INSERT INTO abc (xxxx,yyyy) VALUES (#val1, #val2)";
mCommand.Parameters.AddWithValue("#val1", dtb.Rows[0][0]);
mCommand.Parameters.AddWithValue("#val2", dtb.Rows[0][1]);
// ...

Related

SQL Server stored procedure or function has too many arguments specified, when trying to pass 2 arguments in C#

I am trying to execute a stored procedure called getLastFeatureUpdate.
I will explain below the problem, step by step:
I have created a table in SQL like this:
CREATE TABLE testTable
(
DayTime INT NOT NULL, /*yyddhhmm, 1010102345*/
FeatureNbr SMALLINT NOT NULL,
Val FLOAT(53) NOT NULL
);
I have now created a stored procedure called getLastFeatureUpdate. Important to notice here is that I use 2 parameters #maxDateTime and #tableName, as those are different each time. So I will then pass in those 2 parameters in the C# code that follows in the end.
The stored procedure (if I remove #tableName text from the procedure and the C# code. Then the code does work to mention)
CREATE PROCEDURE getLastFeatureUpdate
#maxDateTime float(53) = 0,
#tableName text
AS
SELECT
test.FeatureNbr,
test.DayTime,
test.Val
FROM
#tableName test
WHERE
DayTime = (SELECT MAX(DayTime)
FROM #tableName
WHERE FeatureNbr = test.FeatureNbr --This is what you are missing
AND DayTime <= #maxDateTime) --10102248
The C# code where I want to return the data from testTable. Which are shown in: MessageBox.Show(d1 + "," + d2 + "," + d3);
But here is where I get the error:
Procedure or function getLastFeatureUpdate has too many arguments specified
Notice, that if I don't pass on the 2nd row here with #tableName, the code will work (I then have to remove #tableName as a parameter also in the stored procedure getLastFeatureUpdate)
cmd.Parameters.Add(new SqlParameter("#maxDateTime", 10102248));
cmd.Parameters.Add(new SqlParameter("#tableName", "testTable")); //If not using this parameter, the code will work
C# code:
void getLastFeatureUpdate()
{
using (SqlConnection conn = new SqlConnection(GetConnectionString()))
{
conn.Open();
// 1. create a command object identifying the stored procedure
SqlCommand cmd = new SqlCommand("getLastFeatureUpdate", conn);
// 2. set the command object so it knows to execute a stored procedure
cmd.CommandType = CommandType.StoredProcedure;
// 3. add parameter to command, which will be passed to the stored procedure
cmd.Parameters.Add(new SqlParameter("#maxDateTime", 10102248));
cmd.Parameters.Add(new SqlParameter("#tableName", "testTable")); //If not using this parameter, the code will work
// execute the command
using (SqlDataReader rdr = cmd.ExecuteReader())
{
// iterate through results, printing each to console
while (rdr.Read())
{
int v1 = (int)rdr["DayTime"];
int v2 = (Int16)rdr["FeatureNbr"];
double v3 = (double)rdr["Val"];
MessageBox.Show(v1 + "," + v2 + "," + v3);
}
}
}
}
static private string GetConnectionString()
{
return "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=C:\\Users\\andre\\source\\repos\\TestDatabaseCreation\\DatabaseTest.mdf;Integrated Security=True;Connect Timeout=30";
}
You cannot parameterize the table name in SQL Server, so: that SQL is invalid, and the CREATE PROC did not in fact run. What the contents of the old proc are: only you can know, but: it isn't the code shown. It was probably a dummy version you had at some point in development. Try typing:
exec sp_helptext getLastFeatureUpdate;
Specifically, the server should have told you:
Msg 1087, Level 16, State 1, Procedure getLastFeatureUpdate, Line 12 [Batch Start Line 0]
Must declare the table variable "#tableName".
Msg 1087, Level 16, State 1, Procedure getLastFeatureUpdate, Line 19 [Batch Start Line 0]
Must declare the table variable "#tableName".

#args is not a parameter for procedure

I am trying to call a stored procedure with a string as parameter (VARCHAR (MAX)) but again and again it tells my #args parameter is not when it certainly is. This is my test procedure:
IF OBJECT_ID ( 'TEST', 'P' ) IS NOT NULL
DROP PROCEDURE TEST;
GO
CREATE PROCEDURE TEST (#args varchar (max)) AS
BEGIN
EXEC sp_execute_external_script
#language = N'R'
, #script = N'OutputDataSet <- as.data.frame(...);'
, #params = N'#args varchar(max)'
, #args = #args
WITH RESULT SETS ((...));
RETURN 0;
END
If I call it from management studio, it works:
SET LANGUAGE ENGLISH
EXEC dbo.TEST #args = 'long string'
GO
but not through C#
public static void Main()
{
Console.WriteLine("Connection test!");
Console.WriteLine("Press ESC to stop");
string ConnectionString = "...";
SqlConnection conn = new SqlConnection(ConnectionString);
SqlCommand cmd = new SqlCommand("TEST");
SqlDataReader rdr = null;
string args = "very long string";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = conn;
cmd.Parameters.Add("#args", SqlDbType.VarChar, -1).Value = args;
conn.Open();
var returnParameter = cmd.Parameters.Add("#ReturnVal", SqlDbType.Int);
returnParameter.Direction = ParameterDirection.ReturnValue;
try { cmd.ExecuteNonQuery(); } // #args is not a parameter for TEST Procedure
catch (SqlException ex)
I am not reusing any parameter which is just a varchar(max). Any ideas?
Finally I found the error which was extremely silly.
Short answer: added the SQL USE statement before dropping and creating the proc.
USE myDB;
GO
Long answer: It turns out I have 2 DBs and I was creating the SP in master but I had another procedure in my testing DB. So although I deleted the SP, there was another one in the other DB with the same name but different parameters, hence the error. As I could not understand why #args was incorrect, I listed the SP params (https://stackoverflow.com/a/3038470/2846161, https://stackoverflow.com/a/3038530/2846161) and it turned out that the procedure was listed even being deleted, therefore it was replicated.

Executing SqlCommand fails due to "string or binary data would be truncated. the statement has been terminated" error

I am trying to save changes made in a GridView of DevExpress into a table of my DataBase, and I was able to do it with the following code:
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings[2].ConnectionString))
{
con.Open();
GridView gv = sender as GridView;
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandText = "UPDATE dbo.tb_Alumno set " + e.Column.FieldName + " = '" + e.Value + "' where pk_alumno = " + gv.GetRowCellValue(gv.FocusedRowHandle, gv.Columns[0]);
cmd.ExecuteNonQuery();
}
}
I have been having this problem since I added parametric command to prevent SQL injection. I have already hardcoded the values for each parameter to encounter the one that provides the error and is the #val parameter:
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings[2].ConnectionString))
{
con.Open();
GridView gv = sender as GridView;
using (SqlCommand cmd = con.CreateCommand())
{
#region Parameters
//cmd.CommandText = "UPDATE dbo.tb_Alumno set " + e.Column.FieldName + " = '" + e.Value + "' where pk_alumno = " + gv.GetRowCellValue(gv.FocusedRowHandle, gv.Columns[0]);
cmd.CommandText = "UPDATE dbo.tb_Alumno set #col = #val where pk_alumno = #id";
cmd.Parameters.AddWithValue("#col", e.Column.FieldName);
cmd.Parameters.AddWithValue("#val", e.Value);
//cmd.Parameters["#val"].SqlDbType = SqlDbType.VarChar;
cmd.Parameters.AddWithValue("#id", gv.GetRowCellValue(gv.FocusedRowHandle, gv.Columns[0]));
#endregion
try
{ cmd.ExecuteNonQuery(); }
catch (Exception xe)
{ MessageBox.Show(xe.Message); }
}
}
Aditional information that I can provide:
The error comes when executing the query
I am using a gridview from DevExpress15.1 in the 'CellValueChanged' event
Data type of the Database is varchar(50) and the parameter is nvarchar
The error comes when the string exceeds 6 characters (even being "hardcoded")
For example, if I use the following parameter it will throw the same error:
cmd.Parameters.AddWithValue("#col", "name");
cmd.Parameters.AddWithValue("#val", "More than 6 characters");
cmd.Parameters.AddWithValue("#id", 1);
This happens with all fields
If I change the middle line to the following I do not have problems at all
cmd.Parameters.AddWithValue("#val", "This<7");
I already tryed to match datatypes as you could see from the commented line, but that throws me no error and does not update the table. I have tested this on other columns too and have the same basic problem.
So my question is, ¿What piece of code should I use to prevent SQL inyection in this particular case?
Here's an example of using a stored procedure that uses dynamic sql. Notice the dynamic sql utilizes sp_executesql which helps prevent sql injection attacks.
The SQL code
create PROCEDURE [dbo].[SP_DynamicUpdate]
-- Add the parameters for the stored procedure here
#col varchar(50) = null,
#val varchar(50) = null,
#id int = 0
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
-- declaring strings
DECLARE #SQLString nvarchar(1024);
DECLARE #ParmDefinition nvarchar(512)
SET #SQLString =
N'Update
dbo.tb_Alumno
set
#col_Param = #val_Param
where
pk_alumno = #id_Param'
-- creating the parameters
SET #ParmDefinition = N'#col_Param varchar(50), ';
SET #ParmDefinition = #ParmDefinition + N'#val_Param varchar(50), ';
SET #ParmDefinition = #ParmDefinition + N'#id_Param int ';
-- Executing the stored procedure
EXECUTE sp_executesql #SQLString,
#ParmDefinition,
#col_Param = #col,
#val_Param = #val,
#id_Param = #id
END
the C# code
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings[2].ConnectionString))
{
GridView gv = sender as GridView;
using (SqlCommand cmd = new SqlCommand("dbo.SP_DynamicUpdate", con))
{
#region Parameters
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#col", e.Column.FieldName);
cmd.Parameters.AddWithValue("#val", e.Value);
cmd.Parameters.AddWithValue("#id", gv.GetRowCellValue(gv.FocusedRowHandle, gv.Columns[0]));
#endregion
try
{
con.Open();
cmd.ExecuteNonQuery();
}
catch (Exception xe)
{
MessageBox.Show(xe.Message);
}
}
}
This will add more security and allow you to test the stored procedure separately with different parameters. You can even add more checks in the stored procedure call - like checks for column names exist.
In terms of sql injection attacks in the way you're doing it, there's not much more you can do.
I was able to find the simplest way to solve my issue and was as follows:
I failed to notice that when I created the bound between the datagrid and the database a tableAdapter and dataSet was automatically created. With this link as reference I found that adapter had an update method, so I used the information so I simply used this code and it worked like a charm, I also added the line to validate the field wich, to be honest I think is not needed.
Validate(); //Or this.Validate();
tb_AlumnoTableAdapter.Update(escuelaDataSet.tb_Alumno);
As before, I put this code under the 'CellValueChanged' event but I assume I can atach it to a button to make it a save button. Thanks to everyone for your answers and I hope this helps other like me.
You may also like to read: How to: Update Data by Using a TableAdapter.

Error converting nvarchar to data type int

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;

Stored Procedure returns nothing

This might be a simple fail on my part, but I just can't figure out where or how.
I've been coding a windows service that is doing a bunch of things. One of which is inserting and getting data from a MS Sql 2005 database through stored procedures.
The following code is part of a windows service and now also a windows form, where both produce the same empty result.
try
{
SqlCommand cmd = new SqlCommand("U_RfId_ProductNumberGet", connectionRFID);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
//SqlParameter paramProd = new SqlParameter();
SqlParameter paramOut = new SqlParameter();
paramOut.ParameterName = "#ProductInformation";
paramOut.Direction = System.Data.ParameterDirection.Output;
paramOut.SqlDbType = System.Data.SqlDbType.VarChar;
paramOut.Size = 50;
cmd.Parameters.Add(paramOut);
cmd.Parameters.AddWithValue("#ProductNumber", content); //content = "1" for testing
connectionRFID.Open();
textBox1.Text = (String)paramOut.Value;
//cmd.Parameters["#ProductInformation"].Value.ToString();
connectionRFID.Close();
}
catch (Exception ex)
{ textBox1.Text = ex.Message;
connectionRFID.Close();
}
And then there's the SP the code is calling. I've tried changing it to only return a resultset instead of a scalar output parameter and then the call to the SP works, but I'd prefer to use the scalar values.
CREATE PROCEDURE U_RfId_ProductNumberGet
#ProductInformation varchar(50) OUTPUT,
#ProductNumber varchar(8)
AS
BEGIN TRAN
SET NOCOUNT ON;
BEGIN
SELECT #ProductInformation
= CAST(vareNummer AS varchar(10))
+ '-' + CAST(vareTekst AS varchar(30))
FROM VareNummerVareTekst
WHERE ProductNumber = #ProductNumber
END
COMMIT TRAN
As a side note: If I execute the SP through SQL Management Studio I get a valid result.
Anyone notice what I've forgotten?
You forgot to execute the command.
cmd.Execute(); // to get a resultset
or
cmd.ExecuteNonQuery(); // to get output parameters but no resultset
should do it depending on whether or not you want a resultset.
you have to use ExecuteNonQuery on command object. SqlCommand Executenonquery
connectionRFID.Open();
cmd.ExecuteNonQuery(); // this missing from your code
textBox1.Text = (String)paramOut.Value;

Categories

Resources