Like vs. "=" для сопоставления строк с использованием SQL Server - PullRequest
8 голосов
/ 19 ноября 2008

Всякий раз, когда я пишу хранимую процедуру для выбора данных на основе строковой переменной (varchar, nvarchar, char), у меня будет что-то вроде:

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

Другими словами, чтобы соответствовать записи, у меня будет

u.username = @username

Но иногда я сталкиваюсь с кодом, который будет использовать LIK E вместо =

u.username like(@username)

Когда бы вы использовали это? Разве это не должно использоваться только тогда, когда вам нужно сопоставление с некоторыми символами подстановки?

EDIT

Спасибо за ответы.

Я думаю, что мне нужно уточнить, что я действительно хотел спросить: может ли быть ситуация, когда предпочтительнее использовать вместо "=" точное совпадение строк? Из ответов я могу сказать, что не будет. Исходя из моего собственного опыта, даже в ситуациях, когда мне нужно игнорировать, например, case и начальные и конечные пробелы, я бы использовал ltrim, rtrim, lower в обеих строках, а затем "=". Еще раз спасибо за ваш вклад.

Ответы [ 9 ]

13 голосов
/ 19 ноября 2008

Вы правы. Использование LIKE не принесет пользы, если вы не сопоставляете символы подстановки. Кроме того, использование его без подстановочных знаков может привести к использованию неэффективного плана запросов.

7 голосов
/ 20 ноября 2008

Солнышко почти все понял :)

Запустите следующее в QA при установке SQL2005 по умолчанию

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

Таким образом, LIKE не совпадает в конечных пробелах, на стороне плана запроса они работают почти одинаково, но объединение '=' работает чуть лучше.

Еще одна вещь, которую вы ДОЛЖНЫ иметь в виду при использовании LIKE, - это правильно экранировать строку.

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

Как правило, люди не используют LIKE для точного сопоставления, потому что проблемы с побегом вызывают всевозможные осложнения и тонкие ошибки, люди забывают сбежать, и возникает боль.

Но ... если вы хотите получить точное точное соответствие, LIKE может решить эту проблему.

Скажем, вы хотите сопоставить имя пользователя с "sam" и не хотите получать "Sam" или "Sam", и, к сожалению, сортировка столбца не учитывает регистр.

Что-то вроде следующего (с добавленным побегом) - путь.

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

Причина, по которой вы делаете двойное совпадение, состоит в том, чтобы избежать сканирования таблицы.

Однако ....

Я думаю, что трюк с варбинарным кастингом менее подвержен ошибкам и легче запоминается.

3 голосов
/ 19 ноября 2008

Если подстановочные знаки не используются, то разница в том, что "=" дает точное совпадение, но LIKE будет сопоставлять строку с конечными пробелами (из SSBO):

При выполнении сравнения строк с как, все символы в шаблон строки являются значительными, включая начальные или конечные пробелы. Если сравнение в запросе вернуть все строки со строкой LIKE 'abc' (abc, сопровождаемый одним пробел), строка, в которой значение этот столбец abc (abc без пространство) не возвращается. Тем не мение, конечные пробелы в выражении которые соответствуют шаблону, являются игнорируются. Если сравнение в запросе вернуть все строки со строкой Как 'abc' (abc без пробела), все строки, начинающиеся с abc и имеющие ноль или больше конечных пробелов возвращаются.

2 голосов
/ 19 ноября 2008

Если вы видите это в коде других людей, возможно, они намеревались позволить человеку передать строку, содержащую шаблон или шаблоны.

2 голосов
/ 19 ноября 2008

С помощью ключевого слова LIKE вы можете сопоставить поле u.username с указанным шаблоном вместо фиксированной строки.

1 голос
/ 06 декабря 2013

Я столкнулся с той же проблемой. Для выполнения аналогичного запроса с = потребовалось около полутора минут. Когда я изменил = на like, запрос был намного быстрее.

  • Попробуйте создать индекс для столбца, с которым вы сравниваете. Это значительно ускорило запрос.
  • Попробуйте запустить sp_updatestats. В моем случае это заставило запрос выполнить около 6 секунд, используя = без индекса и почти мгновенно с индексом.
1 голос
/ 19 ноября 2008

Да - вы правы - его следует использовать только для подстановочных знаков. Его следует использовать с особой осторожностью, особенно в очень больших таблицах на неиндексированных полях, поскольку это может замедлить ваши запросы.

0 голосов
/ 20 ноября 2008

LIKE для сопоставления с подстановочными знаками, где as = (равно) для точных совпадений.

Я также думаю, что он используется для полей, которые были каталогизированы ПОЛНЫМИ ТЕКСТОВЫМИ КАТАЛОГАМИ для сравнения жестких строк.

0 голосов
/ 19 ноября 2008

Да, насколько я знаю, использование like без подстановочных знаков аналогично использованию оператора =. Вы уверены, что во входном параметре нет символов подстановки?

...