LIKE
和=
是不同的操作员.这里的大多数答案都集中在通配符支持上,这不是这些运算符之间的唯一区别!
=
是对数字和字符串进行操作的比较运算符.比较字符串时,比较运算符比较whole strings.
LIKE
是比较character by character的字符串运算符.
更复杂的是,两个操作员都使用了collation,这可能会对比较结果产生重要影响.
让我们首先确定一个例子,其中这些运算符产生明显不同的结果.请允许我引用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,这里没有讨论=
,这意味着=
严格来说不是一个字符串比较函数.
=
Work?SQL Standard § 8.2描述了=
如何比较字符串:
两个字符串的比较如下所示:
a) 如果X的字符长度不等于长度
b) The result of the comparison of X and Y is given by the collating sequence CS.
c) 根据排序顺序,可能会有两个字符串
(重点补充.)
这是什么意思?这意味着在比较字符串时,=
运算符只是当前排序规则的一个薄包装.排序规则是一个具有各种比较字符串规则的库.以下是a binary collation from 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 collation,它支持不区分大小写的比较.代码太长,无法粘贴到这里,但请转到该链接并阅读my_strnncollsp_utf8mb4()
的正文.这种排序可以一次处理多个字节,并且可以应用各种转换(例如不区分大小写的比较).=
运算符完全从排序规则的变幻莫测中抽象出来.
LIKE
Work?SQL Standard § 8.5描述了LIKE
如何比较字符串:
这个<;谓词>;
M LIKE P
如果存在将M划分为子串的情况,则为真
i) M的子串是0或更多连续的序列
ii)如果P的第i子串说明符是任意的
iii)如果P的第i子字符串说明符是任意字符串
iv) If the i-th substring specifier of P is neither an arbitrary character specifier nor an arbitrary string specifier, then the i-th substring of M is equal to that substring specifier according to the collating sequence of the <like predicate>, without the appending of <space> characters to M, and has the same length as that substring specifier.
v) M的子串数等于
(重点补充.)
这很冗长,所以让我们把它分解一下.第二项和第三项分别指通配符_
和%
.如果P
不包含任何通配符,则仅第iv项适用.这是OP提出的有趣 case .
在本例中,它使用当前排序规则将M
中的每个"子字符串"(单个字符)与P
中的每个子字符串进行比较.
底线是,在比较字符串时,=
一次比较整个字符串,而LIKE
一次比较一个字符.两种比较都使用当前排序规则.这种差异在某些情况下会导致不同的结果,正如本文的第一个例子所证明的.
你应该用哪一个?没有人能告诉你这一点——你需要使用一个适合你的用例的.不要过早地通过切换比较运算符进行优化.