9

Whenever I write a stored procedure for selecting data based on string variable (varchar, nvarchar, char) I would have something like:

procedure dbo.p_get_user_by_username(
    @username      nvarchar(256)
as
begin
    select
        u.username
        ,u.email
        --,etc
    from
        sampleUserTable u
    where
        u.username = @username
end

So in other words to match the record I would have

u.username = @username

But sometimes I come across code that would use LIKE in place of =

u.username like(@username)

When would you use it? Shouldn't that be used only when you need some wildcard matching?

EDIT

Thanks for the answers.

I think that I need to clarify that what I was really trying to ask was: if there could be a situation when it was preferred to use like in place of "=" for exact string matching. From the answers I could say that there would not be. From my own experience even in situations when I need to ignore e.g case, and leading and ending spaces i would use ltrim, rtrim, lower on both strings and then "=". Thanks again for your input.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kristof
  • 52,923
  • 24
  • 87
  • 110
  • This code as it stands is really risky with a like clause which is not being escaped ... it means that if you have a username called 'bob_dylan' it will be treated the same as 'bobXdylan' . you need some escaping here for the like clause. – Sam Saffron Nov 20 '08 at 01:19
  • Also, if someone passes a username of say '%' it will force a table scan on your user table AND return all the users ... – Sam Saffron Nov 20 '08 at 01:20
  • Thanks, sambo those are some good points, I was aware of the danger of passing '%' and was not familiar with the escape issue before. What I was really trying to ask is if someone would ever use like in place of "=" for exact string matching – kristof Nov 20 '08 at 10:53
  • kristof, in out-of-the-box sql 2005 installation, like + escaping is good to use if you want an exact match that does not ignore trailing spaces (as opposed to = which ignores trailing spaces) in general people do not use like because the escaping issues will cause subtle bugs – Sam Saffron Nov 20 '08 at 20:57

9 Answers9

13

You are correct. There is no benefit in using LIKE unless you are doing wild card matching. In addition, using it without wildcard could lead to the use of an inefficient queryplan.

Aheho
  • 12,622
  • 13
  • 54
  • 83
  • This is not correct, the optimiser will work fine with like statements on indexed fields, its only when you have wildcards that you have to be very careful. So select * from t where field like '%anything' will force a table scan but like 'hello%' will not (if its indexed) – Sam Saffron Nov 20 '08 at 01:16
  • Also, see my answer, like will not match on trailing spaces in an out-of-the-box sql 2005 installation. – Sam Saffron Nov 20 '08 at 01:18
8

Sunny almost got it right :)

Run the following in QA in a default install of SQL2005

select * from sysobjects where name = 'sysbinobjs   '
-- returns 1 row
select * from sysobjects where name like 'sysbinobjs   '
-- returns 0 rows

So, LIKE does not match on trailing spaces, on the query plan side both perform almost equally, but the '=' join performs a tiny bit better.

An additional thing you MUST keep in mind when using LIKE is to escape your string properly.

declare @s varchar(40) 
set @s = 'escaped[_]_%'

select 1 where 'escaped[_]_%'  like @s 
--Return nothing = BAD 

set @s = '_e_s_c_a_p_e_d_[___]___%' 

select 1 where 'escaped[_]_%'  like @s escape '_'
--Returns 1 = GOOD

In general people do not use LIKE for exact matching, because the escaping issues cause all sorts of complications and subtle bugs, people forget to escape and there is a world of pain.

But ... if you want a real exact match that is efficient, LIKE can solve the problem.

Say, you want to match username to "sam" and do not want to get "Sam" or "Sam " and unfortunately the collation of the column is case insensitive.

Something like the following (with the escaping added) is the way to go.

select * from sysobjects
WHERE name = 'sysbinobjs' and name COLLATE Latin1_General_BIN LIKE 'sysbinobjs'

The reason you do a double match is to avoid a table scan.

However ....

I think the varbinary casting trick is less prone to bugs and easier to remember.

Community
  • 1
  • 1
Sam Saffron
  • 128,308
  • 78
  • 326
  • 506
  • thanks sambo (and upvote of course) for good points about using LIKE. Actually I was not aware of the escape issue. What I was wondering really in my question was if someone would ever use LIKE instead of = for an exact string matching. – kristof Nov 20 '08 at 10:48
3

If no wildcards are used, then the difference is, that "=" makes an exact match, but LIKE will match a string with trailing spaces (from SSBO):

When you perform string comparisons with LIKE, all characters in the pattern string are significant, including leading or trailing spaces. If a comparison in a query is to return all rows with a string LIKE 'abc ' (abc followed by a single space), a row in which the value of that column is abc (abc without a space) is not returned. However, trailing blanks, in the expression to which the pattern is matched, are ignored. If a comparison in a query is to return all rows with the string LIKE 'abc' (abc without a space), all rows that start with abc and have zero or more trailing blanks are returned.

Sunny Milenov
  • 21,990
  • 6
  • 80
  • 106
  • Interestingly enough, this behavior is only true on a unicode field. On an ANSI field, the LIKE does not take spaces into account and they behave identically. This is probably a bug in MSSQL 2008. – Brain2000 Feb 27 '13 at 23:01
2

With the LIKE keyword you can match the field u.username against a specified pattern instead of a fixed "string".

bruno conde
  • 47,767
  • 15
  • 98
  • 117
2

If you're seeing this in other people's code maybe they intended to allow a person to pass in a string that included a pattern or wildcards.

Tom H
  • 46,766
  • 14
  • 87
  • 128
1

I ran into the same problem. It took about a minute and a half to run similar query with =. When I changed = to like the query was much faster.

  • Try creating an index for the column you are comparing with. This sped up the query significantly.
  • Try running sp_updatestats. In my case this made the query run in about 6 seconds using = with out the index and almost instantly with the index.
Chad Carisch
  • 2,422
  • 3
  • 22
  • 30
1

Yes - you are right - it should only be used for wildcard matching. It should be used sparingly especially on very large tables on non-indexed fields as it can slow your queries WAY WAY down.

silverbugg
  • 214
  • 2
  • 7
  • Not really correct doing a like '%tail' will force an index/table scan but like 'head%' will perform quite well if the field is indexed ... – Sam Saffron Nov 20 '08 at 01:12
0

LIKE is for wildcard matching, where as = (equals) is for an exact matches.

I also think it used for fields that have been catalogued by FULL TEXT CATALOGUES for hard core string comparisons.

Pure.Krome
  • 84,693
  • 113
  • 396
  • 647
-1

Yes, as far as I know, using like without any wildcards is the same as using the = operator. are you sure the input parameter doesn't have wildcards in it?

Kevin
  • 7,162
  • 11
  • 46
  • 70