views:

748

answers:

3

I created a proc that will return a list of applicants by lastname. I have a problem searching Applicants with last name that has apostrophe (Example O'Connor). Could you please help finding those applicants:

Below is my Search Code:

if Rtrim(@FirstName) <> ''
begin 
  If(Len(@FirstName) < 30) and (CharIndex('%', @FirstName) = 0) and @FirstName != ''
         Set @FirstName = char(39) + @FirstName + '%' + char(39)
end 

if Rtrim(@LastName) <> ''
begin 
   If(Len(@LastName) < 60) and (CharIndex('%', @LastName) = 0) and @LastName != ''
     Set @LastName = Char(39) + @LastName + '%' + char(39)
end 

#At the end  - --Now build dinamically the filter base on input parameters
if Rtrim(@FirstName) <> ''
    select @Where = @Where + ' and a.FirstName like '+ Rtrim(@FirstName) 

if Rtrim(@LastName) <> ''
  select @Where = @Where + ' and a.LastName like '+ Rtrim(@LastName)
+2  A: 

apostrophes are escaped within T-SQL strings using double apostrophes, e.g.

SELECT * FROM sometable where LastName LIKE '%''%'

Note that the combination of assembling dynamic SQL statements from strings which may contain apostrophes is very dangerous because of the risk of SQL injection attacks. A normal user might have a name like O'Connor, but a savvy attacker might choose a "name" like "O'; TRUNCATE TABLE Customers; --" which could erase data.

At a minimum, if you're dynamically assembling SQL statements from strings, you should be replacing apostrophes with double-apostrophes (e.g. REPLACE (@LastName, '''', '''''')) before injecting that string into SQL.

But, if those strings are coming from users, you should really consider using parameterized queries instead of manually assembling your SQL queries by string concatenation with SQL and parameter strings. Parameterization means that the SQL client API and/or server takes care of turning parameters into "safe" strings. This is the best defense against SQL injection attacks. Take a look at this Jeff Atwood blog post for more details about this.

Justin Grant
A: 

Something like:

...
select @Where = @Where + ' and a.LastName like ' + Replace(Rtrim(@LastName), '''', '''''')
...

(yes, I know, those are lots of quotes, but it works.)

and you need more quotes in the like ' x ' syntax:

select @Where = @Where + ' and a.LastName like ''' + Replace(Rtrim(@LastName), '''', '''''') + ''''

(yes, more and more quotes)

this will generate the correct:

and a.LastName 'like o''conor'
j.a.estevan
I tried What you gave me...but I'm getting an error when i execute the proc.. -- select @Where = @Where + ' and a.LastName like '+ Rtrim(@LastName) select @Where = @Where + ' and a.LastName like ' + Replace(Rtrim(@LastName), '''', '''''')Server: Msg 170, Level 15, State 1, Line 1Line 1: Incorrect syntax near 'O'.
I edited with some more quotes. Love SQL.
j.a.estevan
+2  A: 

Your code looks like you try to build a dynamic SQL WHERE clause. Stop it right there and throw it away, your approach is dangerous and error-prone.

You might want to do something along the lines of this instead:

/* declare a few test variables */
DECLARE @FirstName varchar(30)
DECLARE @LastName  varchar(60)
SET @FirstName = 'First''Name'
SET @LastName = 'Last''Name'

/* these variables are for dynamic SQL execution */
DECLARE @IntVariable int
DECLARE @SQLString nvarchar(500)
DECLARE @ParmDefinition nvarchar(500)

/* define a paramertized SQL query */
SET @SQLString =
 N'SELECT 
     UserId 
   FROM 
     UserTable
   WHERE 
     LastName LIKE ''%'' + @ln + ''%'' 
     AND FirstName LIKE ''%'' + @fn + ''%''
  '

/* define the used parameters and their types */    
SET @ParmDefinition = N'@ln varchar(30), @fn varchar(60)'

/* execute dynamic SQL, syntax- and code-injection safely */
EXECUTE sp_executesql @SQLString, @ParmDefinition,
                      @ln = @LastName, @fn = @FirstName

Be sure to read the MSDN on sp_executesql for more explanation & samples.

Tomalak