Равно (=) против LIKE

При использовании SQL существуют ли какие-либо преимущества использования = в предложении WHERE вместо LIKE?

Без каких-либо специальных операторов LIKE и = совпадают, верно?

Ответ 1

Различные операторы

LIKE и = - разные операторы. Большинство ответов здесь сосредоточены на поддержке подстановочных знаков, что не является единственной разницей между этими операторами!

= - оператор сравнения, который работает с числами и строками. При сравнении строк оператор сравнения сравнивает целые строки.

LIKE - это строковый оператор, который сравнивает символ по символу.

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

Пример мотивации

Сначала определим пример, когда эти операторы производят явно разные результаты. Позвольте мне привести цитату из руководства MySQL:

В стандарте SQL LIKE выполняет сопоставление по каждому символу, поэтому он может выдавать результаты, отличные от оператора сравнения:

mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
+-----------------------------------------+
| 'ä' LIKE 'ae' COLLATE latin1_german2_ci |
+-----------------------------------------+
|                                       0 |
+-----------------------------------------+
mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
+--------------------------------------+
| 'ä' = 'ae' COLLATE latin1_german2_ci |
+--------------------------------------+
|                                    1 |
+--------------------------------------+

Обратите внимание, что эта страница руководства MySQL называется String Comparison Functions, а = не обсуждается, что означает, что = не является строго функцией сравнения строк.

Как работает =?

SQL Standard § 8.2 описывает, как = сравнивает строки:

Сравнение двух символьных строк определяется следующим образом:

a) Если длина символов X не равна длине в символах Y, то более короткая строка эффективно заменяются для целей сравнения с копией которая была расширена до длины более длинной строка путем конкатенации справа от одной или нескольких пэдов символы, в которых символ площадки выбирается на основе CS. Если CS имеет атрибут NO PAD, тогда символ прокладки является зависящий от реализации характер, отличный от любого символа в наборе символов X и Y, который меньше чем любая строка под CS. В противном случае символ прокладки будет.

b) Результат сравнения X и Y задается формулой последовательность группировки CS.

c) В зависимости от последовательности сортировки две строки могут сравниваются как равные, даже если они имеют разную длину или содержат разные последовательности символов. Когда операции MAX, MIN, DISTINCT, ссылки на столбец группировки и Операторы UNION, EXCEPT и INTERSECT ссылаются на характер строки, конкретное значение, выбранное этими операциями, из набор таких равных значений зависит от реализации.

(Акцент добавлен.)

Что это значит? Это означает, что при сравнении строк оператор = представляет собой лишь тонкую оболочку вокруг текущей сортировки. Сортировка - это библиотека, которая имеет различные правила для сравнения строк. Здесь приведен пример двоичной сортировки из MySQL:

static int my_strnncoll_binary(const CHARSET_INFO *cs __attribute__((unused)),
                               const uchar *s, size_t slen,
                               const uchar *t, size_t tlen,
                               my_bool t_is_prefix)
{
  size_t len= MY_MIN(slen,tlen);
  int cmp= memcmp(s,t,len);
  return cmp ? cmp : (int)((t_is_prefix ? len : slen) - tlen);
}

В этом конкретном сопоставлении сравнивается байтовый байт (поэтому он называется "двоичный" - он не дает никакого особого значения для строк). Другие сопоставления могут обеспечивать более сложные сравнения.

Например, здесь приведена сопоставление UTF-8, которая поддерживает нечувствительность к регистру. Код слишком длинный для вставки здесь, но перейдите по этой ссылке и прочитайте тело my_strnncollsp_utf8mb4(). Эта сортировка может обрабатывать несколько байтов за раз и может применять различные преобразования (например, нечувствительность к регистру). Оператор = полностью абстрагируется от капризов сортировки.

Как работает LIKE?

SQL Standard § 8.5 описывает, как LIKE сравнивает строки:

< предикат >

M LIKE P

истинно, если существует разбиение M на подстроки такой, что:

i) Подстрока M является последовательностью 0 или более смежной < символьное представление > s из M и каждый символ Представление > M является частью точно одной подстроки.

ii) Если i-й спецификатор подстроки P является произвольным спецификатор символа, i-я подстрока M является любой одиночной < символьное представление > .

iii) Если i-й спецификатор подстроки P является произвольной строкой specifier, то i-я подстрока M является любой последовательностью 0 или более < символьное представление > s.

iv) Если i-й спецификатор подстроки P не является ни произвольный спецификатор символа или произвольный спецификатор строки, то i-я подстрока M равна этой подстроке в соответствии с последовательностью сортировки < подобный предикат > , без добавления <space> символов в M и имеет ту же длину, что и подстрока Спецификатор.

v) Число подстрок M равно числу спецификаторы подстроки P.

(Акцент добавлен.)

Это довольно многословие, поэтому давайте сломаем его. Пункты ii и iii относятся к подстановочным символам _ и %, соответственно. Если P не содержит подстановочных знаков, применяется только элемент iv. Это представляет интерес для ОП.

В этом случае он сравнивает каждую "подстроку" (отдельные символы) в M с каждой подстрокой в ​​P с использованием текущей сортировки.

Заключение

Суть в том, что при сравнении строк = сравнивает всю строку, а LIKE сравнивает один символ за раз. Оба сравнения используют текущую сортировку. В некоторых случаях это различие приводит к различным результатам, о чем свидетельствует первый пример в этом сообщении.

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

Ответ 2

Оператор equals (=) является "оператором сравнения, сравнивающим два значения для равенства". Другими словами, в выражении SQL он не будет возвращать true, если обе стороны уравнения не равны. Например:

SELECT * FROM Store WHERE Quantity = 200;

Оператор LIKE "реализует сравнение соответствия шаблонов", который пытается сопоставить "строковое значение с строкой шаблона, содержащей символы wild-card". Например:

SELECT * FROM Employees WHERE Name LIKE 'Chris%';

LIKE обычно используется только со строками и равными (я считаю) быстрее. Оператор equals обрабатывает символы wild-card как буквенные символы. Разница в возвращаемых результатах выглядит следующим образом:

SELECT * FROM Employees WHERE Name = 'Chris';

и

SELECT * FROM Employees WHERE Name LIKE 'Chris';

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

SELECT * FROM Employees WHERE Name = 'Chris%';

и

SELECT * FROM Employees WHERE Name LIKE 'Chris%';

Вернет разные результаты, когда использование "=" приведет к результатам только с возвратом "Chris%", и оператор LIKE вернет все, начиная с "Chris".

Надеюсь, что это поможет. Некоторая хорошая информация может быть найдена здесь.

Ответ 3

LIKE и = отличаются. LIKE - это то, что вы использовали бы в поисковом запросе. Он также позволяет использовать такие подстановочные знаки, как _ (символ простого символа) и % (многосимвольный шаблон).

= следует использовать, если вам нужны точные совпадения, и это будет быстрее.

Этот сайт объясняет LIKE

Ответ 4

Это копия/вставка другого моего ответа на вопрос SQL 'как' vs '=' performance:

Личный пример с использованием mysql 5.5: у меня было внутреннее соединение между двумя таблицами, одна из 3 миллионов строк и одна из 10 тысяч строк.

При использовании подобной информации по индексу, указанному ниже (без подстановочных знаков), потребовалось около 30 секунд:

where login like '12345678'

используя "объяснять", я получаю:

enter image description here

При использовании '=' в том же запросе потребовалось около 0,1 секунды:

where login ='12345678'

Используя 'explain', я получаю:

enter image description here

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

Ответ 5

Одно отличие - помимо возможности использовать подстановочные знаки с LIKE - находится в конечных пробелах: оператор = игнорирует конечное пространство, но LIKE не делает.

Ответ 6

Зависит от системы базы данных.

Как правило, без специальных символов да, = и LIKE одинаковы.

Некоторые системы баз данных, однако, могут относиться к настройкам сортировки по-разному с различными операторами.

Например, при сравнении MySQL с строками = on по умолчанию всегда не учитывается регистр, поэтому LIKE без специальных символов одинакова. В некоторых других СУБД LIKE не учитывается регистр, а = нет.

Ответ 7

В этом примере мы считаем само собой разумеющимся, что varcharcol не содержит '' и не имеет пустой ячейки для этого столбца

select * from some_table where varcharCol = ''
select * from some_table where varcharCol like ''

Первый результат выводит 0 строк, а второй показывает весь список. = является строгим совпадением, тогда как действует как фильтр. если фильтр не имеет критериев, все данные действительны.

like - благодаря своей цели работает немного медленнее и предназначен для использования с varchar и аналогичными данными.

Ответ 8

Использование = позволяет избежать конфликтов символов и специальных символов в строке при создании запроса во время выполнения.

Это облегчает жизнь программисту, не избегая всех специальных символов подстановочных знаков, которые могут проскальзывать в предложении LIKE и не дают ожидаемого результата. В конце концов, = - это сценарий использования на 99%, было бы больно каждый раз избегать их.

закатывает глаза в 90 секунд

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

Ответ 9

Чтобы решить исходный вопрос, касающийся производительности, он снизился до использования индекса. Когда происходит простое сканирование таблицы, "LIKE" и "=" идентичны. Когда участвуют индексы, он зависит от того, как формируется предложение LIKE. В частности, каково расположение шаблона (-ов)?


Рассмотрим следующее:

CREATE TABLE test(
    txt_col  varchar(10) NOT NULL
)
go

insert test (txt_col)
select CONVERT(varchar(10), row_number() over (order by (select 1))) r
  from master..spt_values a, master..spt_values b
go

CREATE INDEX IX_test_data 
    ON test (txt_col);
go 

--Turn on Show Execution Plan
set statistics io on

--A LIKE Clause with a wildcard at the beginning
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '%10000'
--Results in
--Table 'test'. Scan count 3, logical reads 15404, physical reads 2, read-ahead reads 15416, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index SCAN is 85% of Query Cost

--A LIKE Clause with a wildcard in the middle
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '1%99'
--Results in
--Table 'test'. Scan count 1, logical reads 3023, physical reads 3, read-ahead reads 3018, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost for test data, but it may result in a Table Scan depending on table size/structure

--A LIKE Clause with no wildcards
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '10000'
--Results in
--Table 'test'. Scan count 1, logical reads 3, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost
GO

--an "=" clause = does Index Seek same as above
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col = '10000'
--Results in
--Table 'test'. Scan count 1, logical reads 3, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost
GO


DROP TABLE test

Также может быть незначительная разница в создании плана запроса при использовании "=" против "LIKE".

Ответ 10

Если вы ищете точное совпадение, вы можете использовать оба: = и LIKE.

Использование "=" в этом случае немного быстрее (поиск точного соответствия) - вы можете проверить это самостоятельно, дважды используя тот же запрос в SQL Server Management Studio, после использования "=" , после использования "LIKE", а затем с помощью "Запроса" / "Включить фактический план выполнения".

Выполните два запроса, и вы должны увидеть свои результаты дважды, плюс два фактических плана выполнения. В моем случае они были разделены на 50% по сравнению с 50%, но план выполнения "=" имеет меньшую "расчетную стоимость поддерева" (отображается, когда вы наводите курсор на крайний левый "SELECT" ), - но опять же, это действительно не большая разница.

Но когда вы начинаете поиск с помощью подстановочных знаков в своем LIKE-выражении, производительность поиска будет уменьшаться. Поиск "LIKE Mill%" все еще может быть довольно быстрым - SQL Server может использовать индекс в этом столбце, если таковой имеется. Поиск "LIKE% expression%" ужасно медленный, поскольку единственный способ, которым SQL Server может удовлетворить этот поиск, - это выполнить полное сканирование таблицы. Поэтому будьте осторожны с вашим LIKE!

Марк

Ответ 11

Помимо подстановочных знаков разница между = AND LIKE будет зависеть как от типа SQL-сервера, так и от типа столбца.

Возьмем этот пример:

CREATE TABLE testtable (
  varchar_name VARCHAR(10),
  char_name CHAR(10),
  val INTEGER
);

INSERT INTO testtable(varchar_name, char_name, val)
    VALUES ('A', 'A', 10), ('B', 'B', 20);

SELECT 'VarChar Eq Without Space', val FROM testtable WHERE varchar_name='A'
UNION ALL
SELECT 'VarChar Eq With Space', val FROM testtable WHERE varchar_name='A '
UNION ALL
SELECT 'VarChar Like Without Space', val FROM testtable WHERE varchar_name LIKE 'A'
UNION ALL
SELECT 'VarChar Like Space', val FROM testtable WHERE varchar_name LIKE 'A '
UNION ALL
SELECT 'Char Eq Without Space', val FROM testtable WHERE char_name='A'
UNION ALL
SELECT 'Char Eq With Space', val FROM testtable WHERE char_name='A '
UNION ALL
SELECT 'Char Like Without Space', val FROM testtable WHERE char_name LIKE 'A'
UNION ALL
SELECT 'Char Like With Space', val FROM testtable WHERE char_name LIKE 'A '
  • Используя MS SQL Server 2012, конечные пробелы будут проигнорированы в сравнении, за исключением LIKE, когда тип столбца VARCHAR.

  • Используя MySQL 5.5, конечные пробелы будут игнорироваться для =, но не для LIKE, как с CHAR и VARCHAR.

  • Используя PostgreSQL 9.1, пробелы имеют значение как с =, так и LIKE, используя VARCHAR, но не с CHAR (см. документация).

    Поведение с LIKE также отличается от CHAR.

    Используя те же данные, что и выше, использование явного CAST в имени столбца также имеет значение:

    SELECT 'CAST none', val FROM testtable WHERE char_name LIKE 'A'
    UNION ALL
    SELECT 'CAST both', val FROM testtable WHERE
        CAST(char_name AS CHAR) LIKE CAST('A' AS CHAR)
    UNION ALL
    SELECT 'CAST col', val FROM testtable WHERE CAST(char_name AS CHAR) LIKE 'A'
    UNION ALL
    SELECT 'CAST value', val FROM testtable WHERE char_name LIKE CAST('A' AS CHAR)
    

    Это возвращает строки для "CAST both" и "CAST col".

Ответ 12

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

С наилучшими пожеланиями...

Ответ 13

Действительно, дело доходит до того, что вы хотите сделать. Если вы имеете в виду точное совпадение, используйте =. Если вы имеете в виду более сумасшедший матч, используйте LIKE. Говорить, что вы имеете в виду, как правило, хорошая политика с кодом.

Ответ 14

В Oracle "как без подстановочных знаков возвращает тот же результат, что и" равно ", но может потребовать дополнительной обработки. Согласно Tom Kyte, Oracle будет рассматривать" как без подстановочных знаков как "равно" при использовании литералов, но не при использовании переменных привязки.

Ответ 15

= и LIKE не то же самое;

  • = соответствует точной строке
  • LIKE соответствует строке, которая может содержать подстановочные знаки (%)