使用SQL时,=在WHERE子句中使用而不是有什么好处LIKE?
=
WHERE
LIKE
没有任何特殊的运营商,LIKE并且=是相同的,对不对?
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标准搂8.2描述了如何=比较字符串:
确定两个字符串的比较如下: a)如果X字符的长度不等于Y字符的长度,则出于比较目的,较短的字符串将有效地替换为已扩展为较长字符串的长度的自身副本通过在一个或多个填充字符的右侧进行串联,可以根据CS选择填充字符。如果CS具有NO PAD属性,则填充字符是与实现相关的字符,不同于X和Y字符集中的任何字符,其比CS之下的任何字符串都少排序。否则,填充字符为。 b)X和Y的比较结果由整理序列CS给出。 c)根据排序顺序,两个字符串即使长度不同或包含不同的字符序列,也可能比较相等。当操作MAX,MIN,DISTINCT引用分组列,而UNION,EXCEPT和INTERSECT运算符引用字符串时,这些操作从一组此类相等值中选择的特定值取决于实现。
确定两个字符串的比较如下:
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()。该排序规则可以一次处理多个字节,并且可以应用各种转换(例如不区分大小写的比较)。该=运营商完全从整理变幻莫测抽象。
my_strnncollsp_utf8mb4()
在SQL标准搂8.5描述了如何LIKE比较字符串:
<谓词> M LIKE P 如果存在将M划分为子字符串的情况,则为true: i)M的子字符串是M的0个或多个连续的<字符表示>的序列,M的每个<字符表示>恰好是一个子字符串的一部分。 ii)如果P的第i个子字符串说明符是任意字符说明符,则M的第i个子字符串说明符是任何单个<字符表示>。 iii)如果P的第i个子串说明符是任意字符串说明符,则M的第i个子串说明符是0或更多<字符表示>的任何序列。 iv)如果P的第i个子字符串说明符既不是任意字符说明符也不是任意的字符串说明符,则根据 的整理顺序,M的第i个子字符串等于该子字符串说明符,而没有将字符附加到M,并具有与该子字符串说明符相同的长度。 v)M的子串数量等于P的子串说明符数量。
<谓词>
M LIKE P
如果存在将M划分为子字符串的情况,则为true:
i)M的子字符串是M的0个或多个连续的<字符表示>的序列,M的每个<字符表示>恰好是一个子字符串的一部分。
ii)如果P的第i个子字符串说明符是任意字符说明符,则M的第i个子字符串说明符是任何单个<字符表示>。
iii)如果P的第i个子串说明符是任意字符串说明符,则M的第i个子串说明符是0或更多<字符表示>的任何序列。
iv)如果P的第i个子字符串说明符既不是任意字符说明符也不是任意的字符串说明符,则根据 的整理顺序,M的第i个子字符串等于该子字符串说明符,而没有将字符附加到M,并具有与该子字符串说明符相同的长度。
v)M的子串数量等于P的子串说明符数量。
这很罗word,所以让我们分解一下。项ii和iii分别指通配符_和%。如果P不包含任何通配符,则仅适用项目iv。OP对此很感兴趣。
_
%
P
在这种情况下,它将使用当前的排序规则将每个“子字符串”(单个字符)M与每个子字符串P进行比较。
M
最重要的是,在比较字符串时,=比较整个字符串,而一次只LIKE比较一个字符。两种比较都使用当前的排序规则。如本文中的第一个示例所示,这种差异在某些情况下会导致不同的结果。
您应该使用哪一个?没有人能告诉您-您需要使用适合您的用例的一种。不要通过切换比较运算符来过早地进行优化。