i am using sqlite client for windows phone for my database. I run into an issue regarding text formatting in this code :
cmd.CommandText = #" Insert into Restaurants (address,description,id,latitude,longitude,name,opening_hours,phone,sandwich,price,updated_at,website,score,rating_count,thumbnail_url) values ('" + r.address + "','" + r.description + "',"+r.id +","+r.latitude+","+r.longitude+",'"+r.name+"','"+r.opening_hours+"','"+r.phone+"','"+r.sandwich+"','"+r.price+"','"+r.updated_at+"','"+r.website+"',"+r.score+","+r.rating_count+",'"+r.thumbnail_url+"')";
cmd.ExecuteScalar();
The issue is that the text fields maybe like "xyz it's abc" and so the ' breaks my update command. How can i keep the ' and make my code run?
Use Parameter instead of hard coded string (query).
cmd.CommandText = #"Insert into Restaurants
(address,description,id,latitude,longitude,name,opening_hours,
phone,sandwich,price,updated_at,website,score,rating_count,thumbnail_url)
values
(#address,#description,#id,#latitude,#longitude,#name,#opening_hours,
#phone,#sandwich,#price,#updated_at,#website,#score,
#rating_count,#thumbnail_url)";
Instead of using a verbatim query string, which is (more) open to attack, use parameters instead:
cmd.Parameters.Add("#Param0", SqlDbType.VarChar, 80).Value = "value";
Consider using stored procedures or parameterised queries rather than direct SQL. This will have the added benefit of making your code less susceptible to issues.
You could escape the characters by doing something like:
cmd.CommandText = cmd.CommandText.Replace("'", "''");
But building a query the way you do could lead to some serious security risks. Have a look at the following article which describes how to change dynamic sql to use sql parameters:
Related
In some C# code, table names passed in via an enum are being inserted into SQL queries using string.Format like so:
const string ADD_SQL = "INSERT INTO {0} (ColumnOne) VALUES (#valueOne)";
const string CLEAR_SQL = "DELETE FROM {0}";
var commandText = string.Format(ADD_SQL , _tableName);
But when I run the Veracode tool it shows this query has possibility of SQL injection when executing.
command.ExecuteNonQuery();
I want to avoid the possibility of SQL injection with the above code. I tried adding a tag (#tablename), but that did not work.
const string ADD_SQL = "INSERT INTO #tablename (Data) VALUES (#valueOne)";
var commandText = ADD_MESSAGE_SQL.Replace("#tablename", _tableName);
How do I avoid this?
There is a good chance that Veracode does not like you putting SQL queries like your current statements, and instead wants to use it's prescribed way of writing this code. And as visible in the documentation in the Repair section, it wants you to use prepared statement to create a parameterized query.
It's upto your choice now. My take on this would be that stored procedures will be better, but if you have to keep query in C#, just don't try to make one query too generic for all scenarios and tables.
Concatenating strings into SQL statements is risky if your strings comes from user input.
While that is not the case you described, I'm guessing the Veracode tool doesn't know where the strings come from, it just see string concatenation and issue a warning.
A better approach would be to write complete SQL statements for each table (Usually I prefer using stored procedures, but that's another topic [you can search for stored procedures vs inline SQL]) and use parameters for values (Identifiers can't be parameterized in SQL, as you already found out).
So instead of
const string ADD_SQL = "INSERT INTO {0} (ColumnOne) VALUES (#valueOne)";
const string CLEAR_SQL = "DELETE FROM {0}";
and adding the table names at run time, here is a better solution:
const string ADD_tableName = "INSERT INTO TableName (ColumnOne) VALUES(#ValueOne)"
const string CLEAR_tableName = "DELETE FROM TableName";
There are even better solutions out there, but this is the easiest fix for the code you presented.
I was looking up how to insert into my database via sql and I noticed the way I had seen a person do an sql statement was different from the way I had done it and and now I'm wondering which way is better.
An example of what I had done in a previous (select) statement.
SqlConnection conn = new SqlConnection(Variables.Default.sqlConString);
conn.Open();
string builtCmd = Variables.Default.returnUserNameSql1 + usersInput + Variables.Default.returnUsernameSql2;
SqlCommand cmd = new SqlCommand(builtCmd, conn);
usersInput is a string.
Variables.Default.returnUserNameSql1 = SELECT [Username] from [dbo].[LoginDetails] WHERE [Username] = '
returnUsernameSql2 = '
What I have seen online (not my query):
cmd.CommandText = "INSERT INTO klant(klant_id,naam,voornaam) VALUES(#param1,#param2,#param3)";
cmd.Parameters.Add(new SqlParameter("#param1", klantId));
cmd.Parameters.Add(new SqlParameter("#param2", klantNaam));
cmd.Parameters.Add(new SqlParameter("#param3", klantVoornaam));
Is the use of the Parameters function (?) better? If so in what way?
Thanks for your time.
I modified my original query thanks to the help of some of the comments here. I'll post it if anyone's interested:
using (SqlConnection conn = new SqlConnection(Variables.Default.sqlConString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(Variables.Default.returnUserNameSql, conn))
{
cmd.Parameters.Add(new SqlParameter(Variables.Default.param1, usersInput));
SqlDataReader reader = cmd.ExecuteReader();
usernameTaken = reader.Read();
cmd.Dispose();
}
conn.Close();
}
Look up "SQL Injection attack" on google. Bobby Tables says hello. And then realize that your way is not bad, it is a security nightmare because everyone with access to your program can execute whatever SQL he wants.
SQL Injection is certainly an important reason not to use string concatenation, but there are a few others:
string delimiters - you'd need to include string delimiters in your SQL statement, and if the values you concatenate include them as well, you'll likely get syntax errors. With parameters you don't need string delimiters, and values with apostro[phes or quotes don't affect the SQL syntax.
string conversion of values - you'd need to convert all non-string values (numbers, dates, etc.) to strings, and ensure that their string represenatations are exactly reversible by the server. This is especially problematic for dates since the same string can represent two different dates depending on the culture of the server. With parameters, the values are passed without translation, so there's no risk that the server misinterprets values.
pre-compilation - with concatenation, the server must reanalyze each query to determine the "best" plan. With parameters, the server can re-use a cached plan since the actual query has been issued before, just with different parameters. This doesn't mean that queries will always perform faster, and in some cases can actually cause bad plans to be used, but it is a consideration if you issue millions of queries that only differ in parameter values.
I am getting an exception:
Incorrect syntax near ','.
in following query: please help.
I have tried it in many ways but not it does not work. Even when I try to insert a single value I still get this exception.
cmd = new SqlCommand("insert into purchaseOrder_master(sup_id,po_date,required_date,tot_amt,uid,potime) values("+supid.Text +",'"+podate.Value.Date+"','"+reqdate.Value.Date+"',"+pocost.Text +","+uid.Text +",'"+potime.Value.TimeOfDay +"')", con);
How often do we have to repeat that you should use parameterized queries?!
using (SqlCommand cmd = new SqlCommand("insert into table (column) values (#param)", conn))
{
cmd.Parameters.AddWithValue("#param", value);
cmd.ExecuteNonQuery();
}
The problems with your code are:
Wide open to SQL injections
DateTime values will not be handled correctly (probably the problem right now)
Strings must be handled properly (quotes)
cmd = new SqlCommand("insert into PurchaseOrder_master(sup_id) values(#val)", con);
cmd.parameters.AddWithValue("#val", supid.Text );
please check data type of date as well. it seems you passing just string for this. if its date time then you need parse string to datetime.
for that conversion use,
DateTime.Parse("stringValue");
if you want to save it without command parameters, then convert your date value and check as mentioned above.
Check out your actual SQL string.
Probably one of your values is an empty string.
That, and what Thorsten said. Use parametrized queries.
i believe the problem is you are putting strings in the insert statement without "'" signs
try:
cmd = new SqlCommand("insert into purchaseOrder_master(sup_id,po_date,required_date,tot_amt,uid,potime) values("+supid.Text +",'"+podate.Value.Date+"','"+reqdate.Value.Date+"','"+pocost.Text +"','"+uid.Text +"','"+potime.Value.TimeOfDay +"')", con);
as you can read here, when doing insert statement, every string needs to be surround with "'"
Try debugging your code and check what exactly the query is formed.
Also i think the possible reason is
insert into purchaseOrder_master(sup_id,po_date,required_date,tot_amt,**uid**,potime
uid is a keyword. replace it with [uid] and check
Change
"+uid.Text +"
to
'"+uid.Text +"'
and
"+supid.Text +"
to
'"+supid.Text +"'
so that
values("+supid.Text +",'"+podate.Value.Date+"','"+reqdate.Value.Date+"',"+pocost.Text +","+uid.Text +",'"+potime.Value.TimeOfDay +"')
reads
values('"+supid.Text +"','"+podate.Value.Date+"','"+reqdate.Value.Date+"',"+pocost.Text +",'"+uid.Text +"','"+potime.Value.TimeOfDay +"')
You have a string.empty in yours variables. Suddenly you generate the following commande :
insert into purchaseOrder_master(sup_id,po_date,required_date,tot_amt,uid,potime) values('value1','value2',,'value3'...
you can use string.format to format your command
Below is an insert statement that is inputting the first value (acctNum) into the second column (itemCode) and vice versa:
string addUpcCode = "INSERT INTO compare1 (acct, itemcode)"
+ "VALUES ('"+acctNum+"', '"+itemCode+"')";
This is not how I want it to work, as I want the first value to go in the first column and the second in the second column. How can I go about this?
Side note: This is a rough draft until I learn more about parameterization. I won't be releasing this code until I learn and implement it.
The given SQL snipplet will do what you want - especially the sequence of columns will be preserved.
I suspect you might have switched your variables, leading to the same phenomen but out of an other reason.
You should use SQL Parameters which also avoids creating a SQL injection problem:
using (SqlCommand command = new SqlCommand("INSERT INTO compare1 (acct, itemcode) VALUES (#AcctNum, #ItemCode)", connection))
{
// Add new SqlParameter to the command.
command.Parameters.Add(new SqlParameter("AcctNum", acctNum));
command.Parameters.Add(new SqlParameter("ItemCode", itemCode));
As you're using C# the string.format function is perfect for this kind of thing
string.format("INSERT INTO compare1(acct, itemCode) Values('{0}','{1}'", acctNum, itemCode);
or
string.format("INSERT INTO compare1 SELECT '{0}','{1}' ", acctNum, itemCode);
But yeah, you probably have them mixed up somewhere else, the order will be kept. Oh and if acctNum is an integer, you won't need the quotation marks around {0}
Edit:
Oh and yeah, definitely look into parameters next
Use parametrized queries to prevent SQL injection and you can solve this matter
command.Parameters.Add("AcctNum", acctNum);
I'm using Microsoft Visual C# 2008 Express Edition with SqlLite. I'm successfully able to open my database and with C# code, add entries to my tables.
When it comes to retriving data, I'm having some issues and have been searching and searching the internet for basic tutorial information on how to do these basic things...
Here's my code... (after I've opened up a connection to the database which is called 'conn' here):
SQLiteCommand cmd = new SQLiteCommand(conn);
cmd.CommandText = "select myField1,myField2 from myTable where myField3 = '" + tempstring + "';";
cmd.CommandType = CommandType.Text;
SQLiteDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
string tmp = reader.GetString(0);
System.Console.WriteLine(" my output = " + tmp);
}
When I execute this... I get no errors and because I get no output on that last line, it looks like the while loop is not executing at all.
I'm a beginner to this stuff... what am I missing and is there a good web resource where I can learn these basic things? I'm pretty comfortable in SQL on it's own... just not integrated in C# like this...
First, remove the hurtful trailing semicolon from the line while (reader.Read());...!
This looks correct to me. Does the property reader.HasRows return true for your query?
A couple of side issues to be aware of are:
Be sure to dispose of your SQL resources by wrapping your objects in using { } blocks.
Consider using parameterized queries instead of injecting the query parameter directly in the SELECT statement.
Answering your question on how to write parameterized queries:
cmd.CommandText = "select myField1,myField2 from myTable where myField3 = #tempString;";
SQLiteParameter param = new SQLiteParameter("#tempString");
cmd.Parameters.Add(param);
// you can modify that value without touching the sql statement (which means you could cache the above command)
param.Value = tempstring;
SQLiteDataReader reader = cmd.ExecuteReader();
[...]
Parameters in SQLite can have several forms which you can find here.
See here for more info on parameterized queries.
Good one, Alex.
In addition to that and since you are beginning with sqlite (you may want to delete second L from the tag), remember that sqlite does not really guaranty data type safety on the database level.
Not to divert you from your Sqlite question, but if you are having comfort issues with Sqlite queries embedded in C#, you could try NHibernate coupled with Fluent NHibernate. These technologies provide an excellent data access mechanism into databases, including Sqlite.
NHibernate requests into Sqlite are very fast, and you won't have to worry about some of the Sqlite idiosyncrasies. If you build out your data-access layer properly with NHibernate, you should be able to up-scale to a more robust database very quickly.