tags:

views:

333

answers:

4

I'm building (c#) sql select commands strings on the fly using LIKE %somestring% conditions. In my search strings I want to be able to handle any character found on a standard PC (US) keyboard (including ~ ! @ # % etc., alt-special chars not required but would be nice to have). I know that single quotes need to be doubled up and perhaps double quotes as well. What other string fixes might be required to ensure correct syntax?

+5  A: 

No fixes required:

SqlCommand cmd = new SqlCommand("select * from Foo where Bar like @p", connection);

SqlParameter p  = new SqlParameter();
param.ParameterName = "@p";
param.Value = pattern;

cmd.Parameters.Add(param);
Anton Gogolev
Shouldn't it be "select * from Foo where Bar like '%' + @p + '%'" ?
Loris
I was aware of parameterized queries. I could do this, but the code would be complicated. I have several fields to search, and a user defined number of strings to search in any field. I'd have to generate input parameters and parameter names dynamically as I loop through the strings.
P a u l
So what's the deal? By concatenating query string you open a huge security hole in your app. If that's fine with you then go ahead.
Anton Gogolev
A: 

Use the quoting function of your SQL access library to defuse strings before passing them onto the SQL parser. This might happen automatically if you use parametrised statements.

David Schmitt
A: 

See Anton Gogolev's answer for a nice code sample.

You only need to escape single quotes in SQL syntax anyhting inbetween 'single quotes' will be considered the string.

Have you considered using parameters instead though? It's a lot better and you don't have to escape single quotes.

SELECT * FROM MyTable WHERE Name LIKE @p0

If the parameter @p0 starts with %SomeText it will be the same as looking for a string which starts with SomeText, %SomeText% will be the same as contains SomeText and finally SomeText% means ends with.

No further escaping is necessary.

John Leidegren
+1  A: 

Apart from doubling up single quotes (or using a parametrised query), will the user know that "_" and "%" are wildcards (any-character and zero-or-more-any-characters respectively), and that "[...]" creates a closure?

To escape those characters there are two routes

WHERE Foo LIKE '%xxx\%yyy%' ESCAPE '\'

or WHERE Foo LIKE '%xxx[%]yyy%'

the second uses the side effect of creating a closure, and avoids having to use the ESCAPE (which in itself needs some thought to choose a character that does not conflict with the rest of the string, or is itself escaped where it occurs)

Note that using 'LIKE %somestring%' will usually require a table scan, and may therefore lead to performance problems - e.g. if you have millions of rows to be checked.

In SQL Server you can use sp_ExecuteSQL if you are generating WHERE clauses by string-concatenation - so that only fields that the user specifies criteria for are included. sp_ExecuteSQL will cache the query and, most times, improve performance. (please ask if that it relevant and you need help)

Kristen
I'm trying to keep the code as generic as possible. I am using subsonic orm with both sql express and sqlite databases. I will only have about 20K rows to search and the performance is very good so far.
P a u l
OK, skip the sp_ExecuteSQl then (which is MSSQL specific). The rest of my comments should be true for all flavours of SQL. Worth keeping an eye on how long your wildcard search takes as the database size grows.
Kristen