Разные операторы
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 называется функциями сравнения строк и =
не обсуждается, что означает, что =
она не является строго функцией сравнения строк.
Как =
работает?
SQL Standard § 8.2 описывает , как =
сравниваются строки:
Сравнение двух строк символов определяется следующим образом:
a) Если длина в символах X не равна длине в символах Y, то более короткая строка фактически заменяется для целей сравнения ее копией, которая была расширена до длины более длинной строки путем объединения справа одного или нескольких символов пэда, где символ пэда выбирается на основе CS. Если CS имеет атрибут NO PAD, то символ pad является зависящим от реализации символом, отличным от любого символа в наборе символов X и Y, который сопоставляется меньше, чем любая строка в CS. В противном случае символ пэда - это.
б) Результат сравнения 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 или более смежных <символьных представлений> из M, и каждая <символьная репрезентация> из M является частью ровно одной подстроки.
ii) Если указатель i-й подстроки P является спецификатором произвольного символа, то i-ая подстрока M является любой отдельной <символьным представлением>.
iii) Если i-ый подстрока P является произвольным строковым спецификатором, то i-ая подстрока M является любой последовательностью из 0 или более <символьных представлений> s.
iv) Если i-й указатель подстроки в P не является ни указателем произвольного символа, ни указателем произвольной строки, то i-ая подстрока M равна этому указателю подстроки в соответствии с последовательностью упорядочения <like-предиката>, без добавление символов <пробел> к M и имеет ту же длину, что и спецификатор подстроки.
v) Количество подстрок M равно количеству спецификаторов подстрок P.
(Акцент добавлен.)
Это довольно многословно, поэтому давайте разберемся с этим. Пункты ii и iii относятся к групповым символам _
и %
, соответственно. Если P
не содержит подстановочных знаков, применяется только пункт iv. Это тот случай, который представляет интерес для ОП.
В этом случае он сравнивает каждую «подстроку» (отдельные символы) M
с каждой подстрокой при P
использовании текущего сопоставления.
Выводы
Суть в том, что при сравнении строк =
сравнивается вся строка, тогда как LIKE
сравнивается один символ за раз. Оба сравнения используют текущую сортировку. Это различие приводит к разным результатам в некоторых случаях, о чем свидетельствует первый пример в этом посте.
Какой из них вы должны использовать? Никто не может сказать вам это - вам нужно использовать тот, который подходит для вашего случая использования. Не преждевременно оптимизируйте, переключая операторы сравнения.