I'm working on my first database application. It is a WinForms application written in C# using a SQLite database.
I've come across some problems, when a apostrophe is used, my SQLite query fails. Here is the structure of my queries.
string SQL = "UPDATE SUBCONTRACTOR SET JobSite = NULL WHERE JobSite = '" + jobSite + "'";
For instance, if an apostrophe is used in the jobSite var, it offsets the other apostrophes in the command, and fails.
So my questions are:
1. How do I escape characters like the apostrophe and semicolon in the above query example?
2. What characters do I need to escape? I know I should escape the apostrophe, what else is dangerous?
Thanks for your help!
Rather use Parameters
There is a previous stack-overflow question about it
Adding parameters in SQLite with C#
if you need more functionality you can also use Entity Framework
http://sqlite.phxsoftware.com/
Sorry not to familiar with the Syntax but the concept should same.
Something like :
SQLiteCommand Command = "UPDATE SUBCONTRACTOR SET JobSite = NULL WHERE JobSite = #JobSite";
Command.Parameters.Add(new SQLiteParameter("#JobSite", JobSiteVariable));
command.ExecuteNonQuery();
to escape an apostrophe add another apostrophe...
so a string like it's should be inserted as it''s
You may also need to escape quotation marks. The way to do this is to use a backslash as an escape charater...
like so... 'and he said\"escape all those quotes\"'
You should also beware of SQL injections... depending on the type of programming language you are using there exist different functions that can help clean out any malicious code.
C# tutorial on SQL Injections for example
You should never concatenate strings to build SQL queries for SQLite - or for any other SQL DB if possible. It makes your code fragile and opens up potential entry points for injection attacks.
The proper way to do it is to use hosted parameters. This approach removes the need for cumbersome string filtering. I am not sure how to do that in C# for SQLite but any decent language binding for SQLite should allow you to use hosted parameters.
Related
I need to filter a sql request by passing a list of id to , this is the command:
var command = "select Software.Name as SoftwareName,SoftwareType.Name as SoftwareType from AssetManagement.Asset as Software inner join AssetManagement.AssetType as SoftwareType on (SoftwareType.Id = Software.TypeId) where Software.Id in (#P)";
cmd.Parameters.AddWithValue("#P", authorizedSoftwaresId);
authorizedSoftwaresId is a list of string , containing data like :
"7D23968B-9005-47A9-9C37-0573629EECF9,F1982165-3F6D-4F35-A6AB-05FA116BA279"
with that it returns to me just one row, I tried adding quotes foreach value but i got "converstion from string caractere to uniqueidentifier failed " exception
This is a pretty common problem and the answer might depend on your database engine and whether you're using ADO.Net, Dapper, etc.
I'll give you some hints from my own experience with this problem on both MS Sql Server and PostgreSQL.
A lot of people think AddWithValue is a devil. You might consider Add instead.
The IN (#P) in your SQL statement might be the source of your problem. Try the Any option instead. See Difference between IN and ANY operators in SQL ; I've had success with this change in similar situations.
If all of your inputs are GUIDs, you might consider changing the type to a collection of GUIDs, although I don't think this is the fix, you have to try everything when you're stuck.
If you have to, you can parse the string version of your collection and add the ticks (') around each value. This choice has consequences, like it may prevent you from using a parameter (#P), and instead construct the final SQL statement you desire (i.e., manually construct the entire WHERE clause through string manipulations and lose the parameter.)
Good luck.
I have searched around for a while for this and have not found anything.
I am storing some pretty long SQL select strings (a shorter one like this:)
string mySelectQuery = "select distribution_stop_information.unique_id_no as stop_unique_id_no,distribution_line_items.unique_id_no as line_unique_id_no, stop_name, stop_address,route_code AS RouteCode, customer_reference," +
"distribution_line_items.datetime_created, rma_number from distribution_stop_information join distribution_line_items on " +
"distribution_line_items.unique_id_no = distribution_stop_information.unique_id_no " +
"where distribution_line_items.datetime_created > '2/22/2017' and customer_no = '91000'";
then passing them by
var Ourstops = (List<stop_data>)db.Query<stop_data>(mySelectQuery);
This is cumbersome and produces hard to read/debug code.
What are some better ways of doing this?
Just a point of clairification - on this project I am not allowed to create any sprocs. Strictly a query only use type, and using postgresql (not that that matters that much here)
This is my preferred formatting, just one guy's opinion:
string mySelectQuery = #"
select
distribution_stop_information.unique_id_no as stop_unique_id_no
,distribution_line_items.unique_id_no as line_unique_id_no, stop_name
,stop_address,route_code AS RouteCode, customer_reference
,distribution_line_items.datetime_created, rma_number
from
distribution_stop_information
join distribution_line_items on distribution_line_items.unique_id_no = distribution_stop_information.unique_id_no
where
distribution_line_items.datetime_created > '2/22/2017' and customer_no = '91000'
";
Benefits
Copy and paste right into sql management studio
Using the # (verbatim literal) eliminates all the quotes and concatenations
Easy to also use $ for string interpolation
commas in front make commenting lines out easier
But do be mindful of SQL Injection and use parameters as much as possible- which is pretty much always. (Edit from comments)
Stored procs or views (SQL specific)
Resources
Use of # to allow line breaks
Configuration files
Content management system (if you have one, and even then not too sure about that)
Entity Framework so you don't have SQL (I'm not a fan BTW. I'd go SPs)
My favourite question! Like you perhaps, I find SQL in string literals the weirdest thing in programming. So weird that I went off and wrote QueryFirst, a visual studio extension for working intelligently with SQL. Your SQL lives in a .sql file, like god intended. You edit it with the marvellous TSQL editor, connected to the database with intellisense for tables and columns and syntax validation. Every time you save the file, QueryFirst checks that the query runs, then (re)generates the C# wrapper that lets you use it. Behind the scenes, QueryFirst compiles your SQL into the binary, and accesses it with GetManifestResourceStream. All your data access is continually integration tested and working, and you have no more SQL hanging around in string literals.
Have you considered getting rid of the strings by using a query builder? There are heaps around eg. https://github.com/cdroulers/awesome-sql-builder.
I have never used it so cannot comment on it specifically.
And even if you don't want to go the heavy EF ORM route you might also look at something like https://github.com/StackExchange/Dapper and avoid constructing SQL by hand.
Aside from it being a potential security risk the hassle in terms of getting quoting right is worth the time and effort investing in a micro ORM.
Being new to C# and postgresql, but not to development and DBs, I'm trying to make the connection from C# .NET to postgresql. I keep running into the same syntax error.
In postgresql I have created a table "Test" with one column "Text".
To insert data into the table, in pgAdmin 4, I use:
insert into public."Test" ("Text") values('It Works!')
This works.
Now I try this in C# where I have a working connection to the database:
1 NpgsqlCommand cmd = new NpgsqlCommand("insert into Test ("Text") values('It Works!')", postconn);
2 cmd.ExecuteNonQuery();
This gives me a compilation error. Apparently from all the double quotes.
If I change the command text to:
"insert into Test ('Text') values('It Works!')"
with single quotes around Text the compiler is happy, but Npgsql gives me a syntax error.
Questions:
In pqsql:
I can see from google that it's possible to get around use the double quotes and the schema reference in psql.
But what does it take?
In C#:
Is there a way to construct the string, so that the compiler will accept it?
pgAdmin 4 is version 1.0
PostgreSQL is version 9.6
C# I believe is the most recent version.
In addition to the comment about escaping your quotes, you really should use parameters instead of literals. It may seem like more work initially, but it's:
Safer (SQL-injection proof)
Easier on the database -- supports compile once, execute many
Avoids having crazy SQL statements within C# that have concacts or string.format all over the place
Avoids the need to single quote literal values and omit quotes for numbers, booleans
Strong datatyping means no formatting (dates, for example)
Here is your code with parameters:
NpgsqlCommand cmd = new NpgsqlCommand("insert into Test (\"Text\") " +
" values(:TEST)", postconn);
cmd.Parameters.AddWithValue("TEST", "It Works");
cmd.ExecuteNonQuery();
Seems like I made your life harder, but your example was a trivial one. As you move to complex SQL statements with multiple parameters and different datatypes, you will see the true value.
On a final rant, while there is nothing technically wrong with making case-sensitive field names, it sure does cause nothing but headaches. Yours is a perfect example. Without the double quotes around the field "Test", you wouldn't have had an issue to begin with.
Currently I learning the asp.net in c#,
I found that if I allow users to input some value in Textbox field,
the (') simbol will cause the sql statement throw error
the good practices to avoid this kind of error is to block the symbol using javascript like "event.keyCode!=222" or replace it by other symbol?
If you are using an ORM (such as entity framework) the (') symbol should not be an issue.
In any case you should handle special characters on the server side (C#) and not the client side (JS) , otherwise your code will be vulnerable to SQL injection and other nasty pests.
It's not only the ' character, there can be more. Check this Which characters are actually capable of causing SQL injection in mysql for better understanding.
And you should do the filtering on server side, do not rely on client side JavaScript as that can be skipped.
Better option is to use a stored procedure, and pass the value submitted by user through a parameter, instead of dynamically constructing SQL strings. That could reduce the risk of SQL injection.
If you want to prevent SQL injection by escaping query string, either use methods which convert apostrophes and special symbols into plain text on server-side, or use parameterized queries with stored procedures.
You can perform Regex.Replace to escape all apostrophes and double minus (comment sign) to plain query string on server side similar to this:
String yourEscapePattern = "[escaped patterns]";
String replacementString = "[replacement here]";
Regex reg = new Regex(yourEscapePattern);
String query = Regex.Replace(input, replacementString);
Parameterized query example:
using (var command = new SqlCommand("[stored procedure name]", connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#Parameter1", SqlDbType).Value = Value1;
// other parameters here
command.ExecuteNonQuery(); // or ExecuteReader
}
you can use
HttpUtility.UrlEncode("some Text'(");
befor saving your text to datebase
So throughout my program I have probably 50 or so text boxes in various places. I know how to replace a single quote with something (in this case ' -> \'), but I am thinking there must be a better way to do this than go through and add specific code for every single text box. I have to do this because when this stuff is getting sent to the database, if there is a single quote, it gives an error. Is there a way to change the default TextBox control behavior so that all textboxes in the program automatically replace all single quotes with \'?
EDIT:
string statement = "select count(*) from users where username='#username'";
MySqlCommand command = new MySqlCommand(statement, conn);
command.Parameters.AddWithValue("#username", username);
if (Convert.ToInt32(command.ExecuteScalar()) == 1)
I have been playing with the paramerterized code and this is what I have right now. From how I understand it, the statement string is basically the same as before, but where I used to have the variable "username" I know use a parameter (which I called #username), then the command is created. Then in the parameters.addwithvalue, it replaces the parameter username, with whatever is in the variable username. Unfortunately, this is not working for me, and I don't really see how it helps because username is still just getting stuck in the command?
EDIT: Found the problem, in the statement you don't need to put single quotes around '#username'
so it should be:
string statement = "select count(*) from users where username=#username";
Don't use concatenation to build SQL queries. Use proper parametrized queries. This will make repeated queries a bit faster and will also eliminate input sanitizing code (replacing ' with \' for example) and SQL injection attacks.
You should be using parameterized queries, not only to resolve the problem you have, but also to reduce your exposure to SQL injection. When you use string concatenation to build SQL queries you are suseptable to SQL injection attackes.
U can use onKeyUp javascript function or asp.net OnTextChanged event to create function that will change quotes.