C# SQL query works in SSMS but not C# - c#

Hey all I am using the following query in my C# program:
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["sqlDevConnection"].ConnectionString);
SqlCommand command = new SqlCommand(Q, con);
con.Open();
command.Parameters.AddWithValue("#val0", buildTblVal.ToString());
command.Parameters.AddWithValue("#val1", recordID);
command.ExecuteNonQuery();
command.Dispose();
con.Close();
Seems I am getting an error of Additional information: Incorrect syntax near the keyword 'WHERE'. when it gets to the command.ExecuteNonQuery();.
The query looks like this:
UPDATE
[tTrip]
SET
#val0
WHERE
RequestID = #val1
And when its populated it looks like this:
UPDATE
tT
SET
RequestType=75,
TripLead='Barker, Bob',
Category=2,
RequestDate='2016-12-15',
ApproxDate='2016-12-15',
AtC='yes',
TStatus='New',
LastModifiedBy='bob\barker',
LastModifiedDate='2017-04-18 10:24 AM'
WHERE
RequestID = 779
I get the error of:
Additional information: Incorrect syntax near the keyword 'WHERE'.
However, when I copy that same query and paste it into SSMS it runs just fine.
What would I be missing?

Parameters are value placeholders, they cannot be sql clauses, statements, etc. That is why it fails because you cannot pass in a whole string for the SET clause as a parameter.
For example, this is how parameters should be used.
UPDATE
tT
SET
RequestType = #requestType,
TripLead = #tripLead,
Category = #category
-- etc
WHERE
RequestID = #requestID
On a side note it is considered best practice to wrap your instances in using blocks where the type implements IDisposable. This ensures that resources are always freed even in the event of an Exception. When working with databases this is a must as it guarantees that connections are not left open until garbage disposal runs (which is non-deterministic).
using(SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["sqlDevConnection"].ConnectionString))
using(SqlCommand command = new SqlCommand(Q, con))
{
con.Open();
// add parameters correctly based on above example
command.Parameters.AddWithValue("#val1", recordID);
command.ExecuteNonQuery();
}

Related

System.Data.SqlClient.SqlException: 'Incorrect syntax near ','.'

I have created this code to add new records to the database however, every time I rum the code I get this error:
System.Data.SqlClient.SqlException: 'Incorrect syntax near ','.'
And I have no idea how to fix this error, I have looked online and tried different ways to fix it and none of them helped or fixed the problem.
The code is found below:
SqlCommand sdk = new SqlCommand("SELECT ([Id],[Title],[JobInfo],[DateSet],[DateDue],[WhoFor]) FROM Information_Schema.Columns FROM JobInformation", ConnectToDatabase);
ConnectToDatabase.Open();
SqlDataReader reader;
reader = sdk.ExecuteReader();
ConnectToDatabase.Close();
I believe it to be the first line of code, but I have no clue where the error could be within it.
I expect you mean something like:
ConnectToDatabase.Open();
using(var sdk = new SqlCommand(
"SELECT [Id],[Title],[JobInfo],[DateSet],[DateDue],[WhoFor] FROM JobInformation",
ConnectToDatabase))
using(var reader = sdk.ExecuteReader())
{
while(reader.Read()) { /* process row */
}
ConnectToDatabase.Close();
However, you may find it easier to use a tool like dapper:
var jobs = ConnectToDatabase.Query<JobInfo>(
"SELECT [Id],[Title],[JobInfo],[DateSet],[DateDue],[WhoFor] FROM JobInformation"
).AsList();
(which does everything including the open/close, and populates the columns into your own JobInfo type that you need to create)
However, you say:
I have created this code to add new records to the database
in which case you'll need to use insert, not select - and the ExecuteNonQuery method of SqlCommand (or the Execute method of "dapper").
For an insert:
using(var cmd = new SqlCommand(#"
insert JobInformation(Title, JobInfo, DateSet, DateDue, WhoFor)
values (#title, #jobInfo, #dateSet, #dateDue, #whoFor)", ConnectToDatabase))
{
cmd.Parameters.AddWithValue("#title", title);
cmd.Parameters.AddWithValue("#jobInfo", jobInfo);
cmd.Parameters.AddWithValue("#dateSet", dateSet);
cmd.Parameters.AddWithValue("#dateDue", dateDue);
cmd.Parameters.AddWithValue("#whoFor", whoFor);
cmd.ExecuteNonQuery();
}
or with dapper:
ConnectToDatabase.Execute(#"
insert JobInformation(Title, JobInfo, DateSet, DateDue, WhoFor)
values (#title, #jobInfo, #dateSet, #dateDue, #whoFor)",
new { title, jobInfo, dateSet, dateDue, whoFor});

Inserting special chars (such as ' or +) into an Access database

I have not much experience with SQL, Access nor C# but I find no solution to a problem that should look quite simple for someone who has more expertise.
Basically, the user fill some textboxes in a Winform and he might insert some "special" characters (at least, special for DB strings) such as '. These data are hence transferred into the database through an OleDb connection; let's say that string myString = this.textBox1.Text is the value that I would like to insert into the field MY_FIELD of the table myTable.
Starting code
My starting code was straight-forward:
OleDbConnection conn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + this.DBstring);
OleDbCommand comm = new OleDbCommand();
comm.CommandText = "INSERT INTO myTable (MY_FIELD) VALUES ('" + myString + "')";
comm.CommandType = CommandType.Text;
comm.Connection = conn;
conn.Open();
comm.ExecuteNonQuery();
conn.Close();
The above code will easily fail in the case where myString is something like guns'n'roses, because the comm.CommandText will be the following string value which is not valid SQL: INSERT INTO myTable(MY_FIELD) VALUES ('guns'n'roses').
Further research
I wasn't obviously the first newbie having this kind of problem. So I searched a bit through Stack Overflow and found the following thread where a guy had an issue inserting brackets into the command string. Hence, I've tried to adapt my code as for the accepted answer:
comm.CommandText = "INSERT INTO myTable (MY_FIELD) VALUES (?)";
comm.Parameters.Add(myString);
but this raises an InvalidCastException saying that The OleDbParameterCollection only accepts non-null OleDbParameter type objects, not String objects.
Could anyone please lead me to what's the best practice to insert any kind of string into the Access database without failing the SQL command due to characters that have a "special" meaning to the SQL interpreter?
You are correct in using OleDbParameter for this. Every time you want to pass values to your database engine you should use parameters. The only problem with your second attempt is the fact that you don't use the correct syntax to create and add a parameter to the command collection
comm.CommandText = "INSERT INTO myTable (MY_FIELD) VALUES (?)";
comm.Parameters.Add("#name", OleDbType.VarWChar).Value = myString;
This of course if your MY_FIELD is a text field, if it is numeric then you need to use the appropriate OleDbType enum.
Said that I would suggest to change your code to this example
string cmdText = "INSERT INTO myTable (MY_FIELD) VALUES (?)";
using(OleDbConnection conn = new OleDbConnection(....))
using(OleDbCommand comm = new OleDbCommand(cmdText, conn))
{
conn.Open();
comm.Parameters.Add("#name", OleDbType.VarWChar).Value = myString;
comm.ExecuteNonQuery();
}
The main difference is the Using Statement. With this syntax your disposable objects (connection and command) are correctly closed and disposed after you have finished to use them releasing any system resource used. And this happens also in case of Exceptions
The .Add method of an OleDbParameterCollection has several overloads, and the ones with a single argument expect that argument to be an OleDbParameter object.
If you want to pass the string value of a parameter then you'll need to use the overload that accepts the Name, Type, and Column Width of the parameter, i.e., this one, and then assign the .Value, like so:
comm.Parameters.Add("?", OleDbType.VarWChar, 255).Value = myString;
And, as #Steve said, you should always use parameters instead of "dynamic SQL" (which is what your first attempt was doing by "gluing" the value into the SQL statement itself).

Must be declared scalar value "#iD_User

`ql = "select ID from Users where Username = '" + txtusername.Text + "';";
cmd = new SqlCommand(sql, Sel_Menu.con);
Sel_Menu.con.Open();
IDD = int.Parse(cmd.ExecuteScalar().ToString()); //here I get int32
Sel_Menu.con.Close();
IDD = 15;
sql = "insert into Action_Log ([ID_User],[Action_NR],[AtWhatTime]) values (#iDUser,#action_NR,getdate())";
cmd = new SqlCommand(sql, Sel_Menu.con);
cmd.Parameters.AddWithValue("#iDUser", IDD+1-1);
cmd.Parameters.AddWithValue("#action_NR", 1);
cmd = new SqlCommand(sql, Sel_Menu.con);
Sel_Menu.con.Open();
cmd.ExecuteNonQuery(); //done also with cmd.ExecuteScalar(); ...
Sel_Menu.con.Close();`
How can I fix this?
still I have "Must be declared scalar value "#iD_User"" error - everything I do - does not change this error - even not to any other error.
Just move the line that reinitialize the SqlCommand before the declarations of the parameters
cmd = new SqlCommand(sql, Sel_Menu.con);
cmd.Parameters.AddWithValue("#iD_User",IDD);
cmd.Parameters.AddWithValue("#action_NR", 1);
cmd.Parameters.AddWithValue("#atWhatTime","getdate()");
You code is adding the parameters to the previous instance of cmd not to the actually executed command. Notice also that the method SqlParameterCollection.Add(string, SqlDbType, int) means, add a parameter with name, type and SIZE. But it doesn't set the value for the parameter.
There is another error. The getDate() function is a T-SQL function. As you are writing it you are passing the string "getDate()" to your last parameter. Move it directly in the Sql command text and remove the third parameter.
sql = #"insert into Action_Log (ID_User,Action_NR,AtWhatTime) values
(#iD_User,#action_NR,getDate())";
Last but not least. In this query you use a parameterized approach (good), while the first one use a string concatenation (bad). Use always parameters to avoid Sql Injection and parsing problems.
You need to initialize your cmd before you try to add your parameters. Move this line before your parameter lines.
cmd = new SqlCommand(sql, Sel_Menu.con);
And SqlParameterCollection.Add(String, SqlDbType, Int32) overload takes size as a third parameter not value. You might need to use other overloads.
You should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks.
By the way, use using statement to dispose your database connections and commands.
Your statement cmd = new SqlCommand(sql, Sel_Menu.con); should come before adding parameters to the command.
Since you are using a single object cmd to execute both commands, it is adding parameters to previous reference and later when you initialize it again using new SqlCommand(sql, Sel_Menu.con) your parameters are lost.
sql = "insert into Action_Log (ID_User,Action_NR,AtWhatTime) values (#iD_User,#action_NR,#atWhatTime)";
cmd = new SqlCommand(sql, Sel_Menu.con);
cmd.Parameters.AddWithValue("#iD_User",SqlDbType.Int, IDD); //I had also tried: "cmd.Parameters.AddWithValue("#iD_User", IDD)"
cmd.Parameters.AddWithValue("#action_NR", 1);
cmd.Parameters.AddWithValue("#atWhatTime",DateTime.Now);
// Either pass `getdate` in your string query or send `DateTime.Now` as parameter.
//Note that DateTime.Now could result in a different value than getdate.
//Thanks to #Steve answer
Consider using parameters with your first command as well, otherwise your code is prone to SQL Injection. Also consider enclosing your command and connection object in using statement, that will ensure the disposal of resources.

Inserting TIMESTAMP data in MYSQL? Error "MYSQL version for the right syntax to use near etc"

I want to add a Timestamp data in my table but got error how can I fix this?
Here is my Proc
CREATE PROCEDURE `db`.`AddMerchantProcessor` (m_id INT, p_id INT, d TIMESTAMP)
BEGIN
INSERT INTO `tbl_merchant_processor`(`merchant_id`, `processor_id`, `date`) VALUES(m_id, p_id, d);
END
timestamp should be wrap with single quotes, eg
CALL AddMerchantProcessor(0, 1, '2012-01-01 00:00:00')
but it's not the proper way of using the Command object. The query should be parameterized.
Here's a little code snippet:
MySqlCommand comm = new MySqlCommand();
comm.Connection = cn;
comm.CommandType = CommandType.StoredProcedure;
comm.CommandText = "AddMerchantProcessor";
comm.Parameters.AddWithValue("m_id", m_id);
comm.Parameters.AddWithValue("p_id", p_id);
comm.Parameters.AddWithValue("d", d);
cn.Open();
comm.ExecuteNonQuery();
you need to:
use using statement for automatic object disposal
put some trycatch for proper exception handling
SOURCES
AddWithValue
Add (preferred method to be used)
Command Object
Using statement
Try-Catch Block

Unicode SQL Query W/ Parameter instead N Prefix

I have an insert query to execute from within a C# against a SQL Server database.
The column I am inserting to is of type nvarchar.
the data I am inserting to that column is non-english.
Is it sufficient for me to use AddWithValue in order to pass the non-english data to the server? like this example:
string dogName = "עברית";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand("INSERT INTO Dogs1(Name) VALUES #Name", connection))
{
command.Parameters.AddWithValue("Name", dogName);
command.ExecuteNonQuery();
}
}
Or must I use the N prefix to declare it unicode? like it says so here.
If I am understanding the question correctly, you can explicitly set the SqlCommand parameter to be a specific data type. You will be able to set it to be nvarchar as shown by the following link: http://msdn.microsoft.com/en-us/library/yy6y35y8.aspx
This below code snippet is taken directly from MSDN:
SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "#CategoryName";
parameter.SqlDbType = SqlDbType.NVarChar;
parameter.Direction = ParameterDirection.Input;
parameter.Value = categoryName;
This uses an explicitly created SqlParameter instance, but it is the same idea by indexing the SqlParameterCollection of the SqlCommand instance.
I believe the link at the bottom is only really talking about values within SQL itself.
As far as I'm aware, the code you've got should be absolutely fine - otherwise there'd be no way of specifying Unicode text.
Of course, it's probably worth validating this - but I'd be very surprised if it didn't work.

Categories

Resources