SQL String issue - c#

I have this INSERT statement,
"INSERT INTO [CustomerInfo] (CustomerName, CustomerEmail, CustomerAddress) " +
$"VALUES ('{name}','{email}','{address}')";
So as you can see on the 2nd line, i have added '$'. This version of the code works, but it's not supported in VS2012.
I'm trying to convert this into something like this but I'm having a lot of issues since it's so very complicated .
"INSERT INTO [CustomerInfo] (CustomerName, CustomerEmail, CustomerAddress) " +
"VALUES (''" + name + "', ''" + email + "', ''" + address + "')";
This version above doesn't work. Basically i'm trying to make a query without using the '$' Any ideas?

Don't do that at all, it exposes you to SQL injection attacks and converions issues. What would a date look like if you tried to pass it using string concatenation? A decimal?
It's actually easier to use parameterized queries :
//Create a SqlCommand that can be reused
SqlCommand _cmdInsert;
var sql="INSERT INTO [CustomerInfo] (CustomerName, CustomerEmail, CustomerAddress) " +
"VALUES (#name,#email,#address)";
var cmd=new SqlCommand(cmd);
cmd.Parameters.Add("#name", SqlDbType.NVarChar, 30);
cmd.Parameters.Add("#email", SqlDbType.NVarChar, 20);
cmd.Parameters.Add("#address", SqlDbType.NVarChar, 50);
_cmdInsert=cmd;
Later, you can use the command directly by setting a connection and parameter values :
using(var connection=new SqlConnection(theConnectionString)
{
_cmdInsert.Connection=connection;
_cmdInsert.Parameters["#name"].Value=someName;
...
connection.Open();
_cmdInsert.ExecuteNonQuery();
}
Parameterized queries pass the strongly-typed values alongside the query in the RPC call. A DateTime is passed as a DateTime (or the binary equivalent) to the server, not as a string. This way, there are no conversion errors. No matter what the value contains, it's never mixed with the query itself so it isn't executed. Even if address contained '); drop table Users;-- it wouldn't be executed.
Another option is to use a microORM like Dapper. Dapper uses reflection to map parameter names and data properties to create and execute parameterized queries:
var insertStmt="INSERT INTO [CustomerInfo] (CustomerName, CustomerEmail, CustomerAddress) " +
"VALUES (#name,#email,#address)";
connection.Execute(insertStmt, new { name=someName,email=someEmail, address=someAddress});
As the project's page shows, you can execute the same query multiple times if you pass an array of parameters :
var myItems=new[]
{
new {name=someName,email=someEmail, address=someAddress}
};
connection.Execute(insertStmt, myItems);

You should use parameterized queries, for example if you are using ADO.NET, use this:
. . .
using(SqlConnection connection = new SqlConnection("yourConnectionString"))
{
SqlCommand cmd = connection.CreateCommand();
cmd.CommandText = #"INSERT INTO [CustomerInfo] (CustomerName, CustomerEmail, CustomerAddress)
VALUES (#Name, #Email, #Address)";
cmd.Parameters.AddRange(new SqlParameter[]
{
new SqlParameter("#Name", name),
new SqlParameter("#Email", email),
new SqlParameter("#Address", address)
});
connection.Open();
cmd.ExecuteNonQuery();
}
. . .
other sql provider type examples you can find here.

Related

How to save data of DateTimePicker into database [duplicate]

I am trying to create an SQL statement using user-supplied data. I use code similar to this in C#:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES ('" + someVariable + "', '" + someTextBox.Text + "');";
var cmd = new SqlCommand(sql, myDbConnection);
cmd.ExecuteNonQuery();
and this in VB.NET:
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES ('" & someVariable & "', '" & someTextBox.Text & "');"
Dim cmd As New SqlCommand(sql, myDbConnection)
cmd.ExecuteNonQuery()
However,
this fails when the user input contains single quotes (e.g. O'Brien),
I cannot seem to get the format right when inserting DateTime values and
people keep telling me that I should not do this because of "SQL injection".
How do I do it "the right way"?
Use parameterized SQL.
Examples
(These examples are in C#, see below for the VB.NET version.)
Replace your string concatenations with #... placeholders and, afterwards, add the values to your SqlCommand. You can choose the name of the placeholders freely, just make sure that they start with the # sign. Your example would look like this:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES (#someValue, #someOtherValue);";
using (var cmd = new SqlCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("#someValue", someVariable);
cmd.Parameters.AddWithValue("#someOtherValue", someTextBox.Text);
cmd.ExecuteNonQuery();
}
The same pattern is used for other kinds of SQL statements:
var sql = "UPDATE myTable SET myField1 = #newValue WHERE myField2 = #someValue;";
// see above, same as INSERT
or
var sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = #someValue;";
using (var cmd = new SqlCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("#someValue", someVariable);
using (var reader = cmd.ExecuteReader())
{
...
}
// Alternatively: object result = cmd.ExecuteScalar();
// if you are only interested in one value of one row.
}
A word of caution: AddWithValue is a good starting point and works fine in most cases. However, the value you pass in needs to exactly match the data type of the corresponding database field. Otherwise, you might end up in a situation where the conversion prevents your query from using an index. Note that some SQL Server data types, such as char/varchar (without preceding "n") or date do not have a corresponding .NET data type. In those cases, Add with the correct data type should be used instead.
Why should I do that?
It's more secure: It stops SQL injection. (Bobby Tables won't delete your student records.)
It's easier: No need to fiddle around with single and double quotes or to look up the correct string representation of date literals.
It's more stable: O'Brien won't crash your application just because he insists on keeping his strange name.
Other database access libraries
If you use an OleDbCommand instead of an SqlCommand (e.g., if you are using an MS Access database), use ? instead of #... as the placeholder in the SQL. In that case, the first parameter of AddWithValue is irrelevant; instead, you need to add the parameters in the correct order. The same is true for OdbcCommand.
Entity Framework also supports parameterized queries.
VB.NET Example Code
This is the example code for the wiki answer in vb.net, assuming Option Strict On and Option Infer On.
INSERT
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES (#someValue, #someOtherValue);"
Using cmd As New SqlCommand(sql, myDbConnection)
cmd.Parameters.AddWithValue("#someValue", someVariable)
cmd.Parameters.AddWithValue("#someOtherValue", someTextBox.Text)
cmd.ExecuteNonQuery()
End Using
UPDATE
Dim sql = "UPDATE myTable SET myField1 = #newValue WHERE myField2 = #someValue;"
' see above, same as INSERT
SELECT
Dim sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = #someValue;"
Using cmd As New SqlCommand(sql, myDbConnection)
cmd.Parameters.AddWithValue("#someValue", someVariable)
Using reader = cmd.ExecuteReader()
' ...
End Using
' Alternatively: Dim result = cmd.ExecuteScalar()
' if you are only interested in one value of one row.
End Using

ASP.NET SqlParameter [duplicate]

I am trying to create an SQL statement using user-supplied data. I use code similar to this in C#:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES ('" + someVariable + "', '" + someTextBox.Text + "');";
var cmd = new SqlCommand(sql, myDbConnection);
cmd.ExecuteNonQuery();
and this in VB.NET:
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES ('" & someVariable & "', '" & someTextBox.Text & "');"
Dim cmd As New SqlCommand(sql, myDbConnection)
cmd.ExecuteNonQuery()
However,
this fails when the user input contains single quotes (e.g. O'Brien),
I cannot seem to get the format right when inserting DateTime values and
people keep telling me that I should not do this because of "SQL injection".
How do I do it "the right way"?
Use parameterized SQL.
Examples
(These examples are in C#, see below for the VB.NET version.)
Replace your string concatenations with #... placeholders and, afterwards, add the values to your SqlCommand. You can choose the name of the placeholders freely, just make sure that they start with the # sign. Your example would look like this:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES (#someValue, #someOtherValue);";
using (var cmd = new SqlCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("#someValue", someVariable);
cmd.Parameters.AddWithValue("#someOtherValue", someTextBox.Text);
cmd.ExecuteNonQuery();
}
The same pattern is used for other kinds of SQL statements:
var sql = "UPDATE myTable SET myField1 = #newValue WHERE myField2 = #someValue;";
// see above, same as INSERT
or
var sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = #someValue;";
using (var cmd = new SqlCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("#someValue", someVariable);
using (var reader = cmd.ExecuteReader())
{
...
}
// Alternatively: object result = cmd.ExecuteScalar();
// if you are only interested in one value of one row.
}
A word of caution: AddWithValue is a good starting point and works fine in most cases. However, the value you pass in needs to exactly match the data type of the corresponding database field. Otherwise, you might end up in a situation where the conversion prevents your query from using an index. Note that some SQL Server data types, such as char/varchar (without preceding "n") or date do not have a corresponding .NET data type. In those cases, Add with the correct data type should be used instead.
Why should I do that?
It's more secure: It stops SQL injection. (Bobby Tables won't delete your student records.)
It's easier: No need to fiddle around with single and double quotes or to look up the correct string representation of date literals.
It's more stable: O'Brien won't crash your application just because he insists on keeping his strange name.
Other database access libraries
If you use an OleDbCommand instead of an SqlCommand (e.g., if you are using an MS Access database), use ? instead of #... as the placeholder in the SQL. In that case, the first parameter of AddWithValue is irrelevant; instead, you need to add the parameters in the correct order. The same is true for OdbcCommand.
Entity Framework also supports parameterized queries.
VB.NET Example Code
This is the example code for the wiki answer in vb.net, assuming Option Strict On and Option Infer On.
INSERT
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES (#someValue, #someOtherValue);"
Using cmd As New SqlCommand(sql, myDbConnection)
cmd.Parameters.AddWithValue("#someValue", someVariable)
cmd.Parameters.AddWithValue("#someOtherValue", someTextBox.Text)
cmd.ExecuteNonQuery()
End Using
UPDATE
Dim sql = "UPDATE myTable SET myField1 = #newValue WHERE myField2 = #someValue;"
' see above, same as INSERT
SELECT
Dim sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = #someValue;"
Using cmd As New SqlCommand(sql, myDbConnection)
cmd.Parameters.AddWithValue("#someValue", someVariable)
Using reader = cmd.ExecuteReader()
' ...
End Using
' Alternatively: Dim result = cmd.ExecuteScalar()
' if you are only interested in one value of one row.
End Using

Insert into DateTime (from C# to MySQL)

I Just Keep Having this Error:
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 '2014-10-08 19:39:57)' at line 1
public string ObtenerFechaHora()
{
string query = "select CURRENT_TIMESTAMP() as Fecha";
OpenConnection();
MySqlCommand cmd = new MySqlCommand(query, connection);
cmd.ExecuteNonQuery();
DateTime e = (DateTime)cmd.ExecuteScalar();
CloseConnection();
return e.ToString("yyyy-MM-dd H:mm:ss");
}
Then i insert ("Fecha" is the DateTime Column)
string query = "INSERT INTO actividad (idTerminal, Proceso, Nombre, Tiempo, Fecha) VALUES('" + idTerminal + "', '" + Proceso + "', '" + Nombre + "', '1,'" + this.ObtenerFechaHora() + ")";
I been used loot of formats and i keep having error, for example:
e.ToString("yyyy-MM-dd H:mm:ss");
e.ToString("yyyy-MM-dd HH:mm:ss");
e.ToString("dd-MM-yyyy H:mm:ss");
e.ToString("yyyy-dd-MMH:mm:ss");
Also with "/" instead of "-"
Any help here?
The problem isn't with the format of the datetime string; the problem is in the SQL text of the INSERT statement, right before the value is appended. For debugging this, you could output the query string and inspect it.
The problem is in the SQL text here:
+ "', '1,'" +
There needs to be a comma between that literal and the next column value. It looks like you just missed a single quote:
+ "', '1','" +
^
A potentially bigger problem is that your code appears to be vulnerable to SQL Injection. Consider what happens when one of the variables you are including into the SQL text includes a single quote, or something even more nefarios ala Little Bobby Tables. http://xkcd.com/327/.
If you want a column value to be the current date and time, you don't need to run a separate query to fetch the value. You could simply reference the function NOW() in your query text. e.g.
+ "', '1', NOW() )";
You excuted twice
//cmd.ExecuteNonQuery();
DateTime e = (DateTime)cmd.ExecuteScalar();
Should be only one time.
Then like #sgeddes said in the comments use parameterized queries, they avoid errors and sql injections.
The approach that you have used is not the best approach to write SQL command. You should use sql parameters in the Query. Your code is vulnerable to SQL Injected and obviously it is not the best approach.
Try using something like this:
string commandText = "UPDATE Sales.Store SET Demographics = #demographics "
+ "WHERE CustomerID = #ID;";
SqlCommand command = new SqlCommand(commandText, connection);
command.Parameters.Add("#ID", SqlDbType.Int);
command.Parameters["#ID"].Value = customerID;

Cant find error (Unclosed quotation mark after the character string ''.)

Code snippet:
dbCommand = new SqlCommand("sp_EVENT_UPATE '"
+ currentEvent.EventID + "','" + currentEvent.Description + "','"
+ currentEvent.DisciplineID + "'", dbConnection);
Where am I missing a quote?
Use parameters instead of hardcoded strings.
using(dbCommand = new SqlCommand())
{
dbCommand.CommandText="sp_EVENT_UPATE";
dbCommand.Connection=dbConnection;
dbCommand.CommandType=CommandType.StoredProcedure;
dbCommand.Parameters.AddWithValue("#EventID",currentEvent.EventID);
....
dbConnection.Open();
dbCommand.ExecuteNonQuery();
dbConnection.Close();
}
The un-closed quotation mark is most likely in one of your variables. Further, building your query like that makes you vulnerable to a sql injection attack.
Look into adding your values using the SqlCommand.Parameters list.
Something like this
dbCommand = new SqlCommand("sp_EVENT_UPATE #eventId, #description, #disciplineID", dbConnection);
dbCommand.Parameters.AddWithValue("#peventId",currentEvent.EventID);
dbCommand.Parameters.AddWithValue("#description",currentEvent.Description);
dbCommand.Parameters.AddWithValue("#disciplineID",currentEvent.DisciplineID);
Your currentEvent.Description could potentially have that single quote which is breaking the syntax of that SQL statement. You should always use prepared statement/commands to counter this kind of scenarios.

asp.net SQL Server insert statement tidyup + error

I have a form which inserts data into a database.
There are certain fields that are not always going to be needed.
When I leave these blank in my code I get a error saying.
Column name or number of supplied values does not match table
definition.
This is how I have the database setup. SQL Server 2008
[youthclubid]
[youthclubname]
[description]
[address1]
[address2]
[county]
[postcode]
[email]
[phone]
Here is the code that I have connecting to the database and doing the insert.
connection.Open();
cmd = new SqlCommand("insert into youthclublist values ('" + youthclubname.Text + "', '" + description.Text + "','" + address1.Text + "','" + address2.Text + "', '" + county.Text + "', '" + postcode.Text + "', '" + email.Text + "', '" + phone.Text + "')", connection);
cmd.ExecuteNonQuery();
You have two major problems:
1) concatenating together your SQL statement is prone to SQL injection attacks - don't do it, use parametrized queries instead
2) You're not defining which columns you want to insert in your table - by default, that'll be all columns, and if you don't provide values for all of them, you'll get that error you're seeing.
My recommendation: always use a parametrized query and explicitly define your columns in the INSERT statement. That way, you can define which parameters to have values and which don't, and you're safe from injection attacks - and your performance will be better, too!
string insertStmt =
"INSERT INTO dbo.YouthClubList(Youthclubname, [Description], " +
"address1, address2, county, postcode, email, phone) " +
"VALUES(#Youthclubname, #Description, " +
"#address1, #address2, #county, #postcode, #email, #phone)";
using(SqlConnection connection = new SqlConnection(.....))
using(SqlCommand cmdInsert = new SqlCommand(insertStmt, connection))
{
// set up parameters
cmdInsert.Parameters.Add("#YouthClubName", SqlDbType.VarChar, 100);
cmdInsert.Parameters.Add("#Description", SqlDbType.VarChar, 100);
.... and so on
// set values - set those parameters that you want to insert, leave others empty
cmdInsert.Parameters["#YouthClubName"].Value = .......;
connection.Open();
cmdInsert.ExecuteNonQuery();
connection.Close();
}
The first major issue is that you are concatenating inputs in the query. This makes your application highly vulnerable to SQL Injection. Do not do this. Use a parametrized query.
The regular syntax for insert statement is like this:
Insert into <TableName> (Col1, Col2...Coln) values (val1, val2...valn)
If you need to insert only a selected set of columns, you need to provide the list of columns you are inserting data into in the column list.
If you do not specify the column list, the indication is that you are inserting data to each one of them.
So you may check for the input and if it is not there, you may omit the respective column.
The other better way is use a stored proc. That will ease out the issue.
This not way to do the code you make use of SqlParameter for this kind of statement.
So your code something like
SqlConnection thisConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["Northwind_ConnectionString"].ConnectionString);
//Create Command object
SqlCommand nonqueryCommand = thisConnection.CreateCommand();
try
{
// Create INSERT statement with named parameters
nonqueryCommand.CommandText = "INSERT INTO Employees (FirstName, LastName) VALUES (#FirstName, #LastName)";
// Add Parameters to Command Parameters collection
nonqueryCommand.Parameters.Add("#FirstName", SqlDbType.VarChar, 10);
nonqueryCommand.Parameters.Add("#LastName", SqlDbType.VarChar, 20);
nonqueryCommand.Parameters["#FirstName"].Value = txtFirstName.Text;
nonqueryCommand.Parameters["#LastName"].Value = txtLastName.Text;
// Open Connection
thisConnection.Open();
nonqueryCommand.ExecuteNonQuery();
}
catch (SqlException ex)
{
// Display error
lblErrMsg.Text = ex.ToString();
lblErrMsg.Visible = true;
}
finally
{
// Close Connection
thisConnection.Close();
}
You need to tell SQL server that which field you want to insert like
insert into youthclublist(youthclubid, youthclubname, ....) values ('" + youthclubname.Text + "', '" + description.Text + "'.....
and you are fine.
Though new into programming, the easiest way i know to insert into a database is to create a "save" stored procedure, which is then called up through your connection string. Believe me, this is the best way.
Another way around is to use LINQ to SQL. i found this much more easier. Follow this steps.
Add a new LINQ to SQL Classes to your project. Make sure the file extension is '.dbml'. Name it your name of choice say "YouthClub.dbml"
Connect your Database to Visual Studio using the Server Explorer
Drag your table to the OR Designer.(I'm not allowed to post images).
You can now save to the Database with this code
//Create a new DataContext
YouthClubDataContext db = new YouthClubDataContext();
//Create a new Object to be submitted
YouthClubTable newYouthClubRecord = new YouthClubTable();
newYouthClubRecord.youthlubname = txtyouthclubname.Text;
newYouthClubRecord.description = txtdescription.Text;
newYouthClubRecord.address1 = txtaddress1.Text;
newYouthClubRecord.address2 = txtaddress2.Text;
newYouthClubRecord.county = txtcounty.Text;
newYouthClubRecord.email = txtemail.Text;
newYouthClubRecord.phone = txtphone.Text;
newYouthClubRecord.postcode = txtpostcode.Text;
//Submit to the Database
db.YouthClubTables.InsertOnSubmit(newYouthClubRecord);
db.SubmitChanges();
Hope this time I have given a real answer

Categories