views:

345

answers:

7

I am looking for something that works in SQL Server similar to the @ symbol in c# which causes a string to be taken as it's literal. Eg:

string text = "abcd\\efg";
Output of text = abcd\efg

string text = @"abcd\\efg";
Output of text = abcd\\efg

Note how the @ affected the string to take every character as is.

Now I am not sure this is possible but here is my issue and maybe there is a better way to solve this. Consider the following basic query:

SELECT [Name] 
  FROM [Test] 
 WHERE [Name] LIKE (@searchText + '%')

My issue is if they put a %, _ or any other of those special characters that can affect my like clause. I want the match to act just like a 'starts with' function. So is there anything I can apply to the @searchText to say take this literally or is there possbibly a better solution that I am not thinking of?

Edit: I do not want the solution to be client side cleaning. I need this stored proc to work without relying on the data being passed in being cleaned.

A: 

Each character to be treated literally should be enclosed in square brackets. A right bracket is taken literally directly so don't enclose that one.

Joshua
A: 

I'd sanitize the string in the front-end application rather than try and do hokey stuff in SQL to work around this.

Wyatt Barnett
I think that's the plan.
recursive
What if you ACTUALLY need percent signs or underscores in text?
Neil N
I don't want my stored proc to rely on the caller passing it cleaned data.
Kelsey
+4  A: 

In TSQL, you can wrap the % and _ characters in brackets like so [%] [_] this tells SQL to treat them as literals.

I have tested and verified this works in SQL Server 7.0, 2000, and 2005.

http://msdn.microsoft.com/en-us/library/aa933232%28SQL.80%29.aspx

Neil N
So doing "...where columnName LIKE '[%]foo%'" would actually search for any value that starts with "%foo" (the % acting as a literal, not as a wildcard? I was not aware of that.
Adam Robinson
This isn't true for string literals.
David
Ah, I stand corrected. I've never seen this used in 10 years. :-P
David
I've been doing SQL for 10 years too, and just YESTERDAY learned this because I couldn't get like statements to work with underscores. So I read the docs and saw the light.
Neil N
So what happens if my string has a [ in it already like: ab[%]cd and I want it to actually match exactly?
Kelsey
Kelsey, read the docs, they explain how to escape brackets as well.
Neil N
@Kelsey - then you can define an escape charater using LIKE @text ESCPAPE '~' and your text would be ab~[~%~]cd. See my updated/corrected answer below.
David G
+1 for the details but I have to award the answer to gbn as he included code that I could just cut and past and add. I would like to have given you a +2 though :)
Kelsey
A: 

If you don't want to modify the incoming text, you can use the "LEFT" function to create your own "STARTSWITH":

SELECT [Name] 
  FROM [Test] 
 WHERE @searchText = LEFT( [Name], LEN( @searchText ) )

(Note that you probably need to do extra work to handle the case of NULLs or empty string.)

EDIT: Removed the incorrect statement about using "LIKE" to search for "%".

David
It appears to be very common misconception, but you CAN escape % and _ in LIKE comparisons
Neil N
A: 

If you parameterize your query you don't need to worry about it.

UPDATE

As recursive stated in the comments, % still needs to be escaped even in parameterized queries, I didn't realize linq to sql was doing it automagically when I tested.

You can use ESCAPE 'x' where x is the character you wish to be the escape character. Linq to SQL does it like this

WHERE [Name] LIKE @searchText ESCAPE '~'

where @searchText = [some text with a~% character%]

or as others have stated it can be escaped with [%]

view the documentation

David G
This is not true. Try it yourself.
recursive
The question in the OP is unrelated to Parameterized queries. The question is valid with or without params
Neil N
I wasn't aware of that. Linq to SQL does it automatically. I've corrected my answer.
David G
A: 

From the docs:

Syntax

*match_expression* [ NOT ] LIKE pattern [ ESCAPE *escape_character* ]

Use the ESCAPE option like so:

SELECT [Name] 
  FROM [Test] 
 WHERE [Name] LIKE (REPLACE(@searchText, '%', '%%') + '%') ESCAPE '%'
recursive
I thought of this route but would I need to do this for %, _, [, ], and any other characters? That seems like a lot of searching and replacing.
Kelsey
+4  A: 

To search for "%" as a literal not wildcard in a string, it needs escaped as [%].

Now, SQL Server only need 3 characters escaping: % : [

So, create a scalar udf to wrap this:

REPLACE(REPLACE(REPLACE(@myString, '%', '[%]'), '_', '[_]'), '[', '[[]')

Because of the simplicity (aka: very limited) pattern matching in SQL, nothing more complex is needed...

gbn
This code works. Thanks for the snippet and explination.
Kelsey