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