当前位置:  开发笔记 > 编程语言 > 正文

等于(=)与LIKE

如何解决《等于(=)与LIKE》经验,为你挑选了10个好方法。

使用SQL时,=WHERE子句中使用而不是LIKE

没有任何特殊的操作员,LIKE并且=是一样的,对吧?



1> Mark E. Haas..:
不同的运营商

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下的任何字符串.否则,填充字符是a.

b)比对序列CS给出X和Y的比较结果.

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标准§8.5描述了如何LIKE比较字符串:

<谓词>

M LIKE P

如果存在将M划分为子串的情况,则为真:

i)M的子串是M的0个或更多个连续<字符表示>的序列,并且M的每个<字符表示>是恰好一个子串的一部分.

ii)如果P的第i个子字符串说明符是任意字符说明符,则M的第i个子字符串是任何单个<字符表示>.

iii)如果P的第i个子字符串说明符是任意字符串说明符,则M的第i个子字符串是0或更多<字符表示> s的任何序列.

ⅳ)如果P的第i子串符既不是任意的字符说明符,也不是一个任意字符串符,则M的第i子串根据<像谓词>的排序序列等于子指示符,而不将字符附加到M,并且具有与该子字符串说明符相同的长度.

v)M的子串数等于P的子串指定符的数量.

(重点补充.)

这很啰嗦,所以让我们把它分解.项目ii和iii分别表示通配符_%.如果P不包含任何通配符,则仅应用第iv项.这是OP提出的利益案例.

在这种情况下,比较在每个"子"(单个字符)M对在每个子P使用当前排序规则.

结论

最重要的是,在比较字符串时,=比较整个字符串,同时LIKE比较一个字符.两种比较都使用当前的排序规则.在某些情况下,这种差异会导致不同的结果,如本文第一个例子所示.

你应该使用哪一个?没有人可以告诉你 - 你需要使用一个对你的用例正确的那个.不要通过切换比较运算符来过早优化.


*这*是正确的答案.我们知道`LIKE'做了什么,但是这个答案很棒地解释了使用`LIKE`而没有'%`或`_`存在*完全没有*与使用`=`相同.愿你的答案收到一千个赞成票.
"EQUALS逐字节比较两个数据":过于简单,而且往往不是真的,因为可以使用COLLATE修改EQUALS(=)行为,从而导致比较字符类而不是字符.例如,请参阅http://dev.mysql.com/doc/refman/5.0/en/charset-collat​​e.html(MySQL)或http://sqlmag.com/blog/forcing-collat​​ion-where-clause-22-jun -2011(SQL Server).
棒极了,谢谢你的更新...投票逆转:)
这似乎不再适用:`set charset latin1;``SELECT'ä'='ae'COLLATE latin1_german2_ci;`给0,'SELECT'ä'LIKE'''COLLATElatin1_german2_ci;`也给0.

2> achinda99..:

equals(=)运算符是"比较运算符比较两个值的相等性".换句话说,在SQL语句中,除非等式的两边相等,否则它不会返回true.例如:

SELECT * FROM Store WHERE Quantity = 200;

LIKE运算符"实现模式匹配比较",尝试将"字符串值与包含通配符的模式字符串匹配".例如:

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

LIKE通常只用于字符串和equals(我相信)更快.equals运算符将通配符视为文字字符.返回结果的差异如下:

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"开头的任何内容.

希望有所帮助.这里可以找到一些好的信息.


我的印象是OP知道何时使用LIKE以及何时使用=,他只是想知道在没有通配符时是否存在性能差异.这个答案简要介绍了这一点,但我觉得95%的答案并不真正相关.
这个答案太可怕了.LIKE和'='是完全不同的运算符,但恰好在一些小的子集中表现相似.为了后人,请在此处阅读其余的回复,或者至少谷歌为"mysql like",然后再将其提交到内存中.
另一方面,这个答案回答了我的问题和google搜索.有时,如果答案回答问题的标题,那么它就像内容一样好.

3> WalterJ89..:

LIKE并且=是不同的.LIKE是你在搜索查询中使用的.它还允许使用通配符_(简单字符通配符)和%(多字符通配符).

= 如果你想要完全匹配,应该使用它会更快.

这个网站解释说 LIKE



4> Aris..:

这是我的另一个答案的复制/粘贴问题SQL'''vs'='performance:

使用mysql 5.5的个人示例:我在2个表之间有一个内连接,一个是300万行,另一个是万行.

当在索引上使用like如下(没有通配符)时,花了大约30秒:

where login like '12345678'

使用'解释'我得到:

在此输入图像描述

在同一查询中使用'='时,大约需要0.1秒:

where login ='12345678'

使用'explain'我得到:

在此输入图像描述

正如您所看到的,like完全取消了索引查找,因此查询花费了300倍的时间.



5> ISW..:

除了使用带有LIKE的通配符的可能性之外,一个区别在于尾随空格:=运算符忽略尾随空格,但LIKE不会.


虽然这适用于MySQL和MS SQL,但这不适用于PostgreSQL.

6> ʞɔıu..:

取决于数据库系统.

通常没有特殊字符,是,=和LIKE是相同的.

但是,某些数据库系统可能会以不同的运算符对待排序规则设置.

例如,在MySQL中,与= on字符串的比较默认情况下始终不区分大小写,因此没有特殊字符的LIKE是相同的.在其他一些RDBMS的LIKE是不区分大小写的,而=不是.



7> 小智..:

对于此示例,我们理所当然地认为varcharcol不包含''并且没有针对此列的空单元格

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

第一个导致0行输出,而第二个导出整个列表.=是严格匹配的情况,而像过滤器一样.如果过滤器没有标准,则每个数据都有效.

喜欢 - 由于它的目的,它的工作速度稍慢,并且打算用于varchar和类似的数据.



8> Coincoin..:

在运行时生成查询时,使用=避免字符串中的通配符和特殊字符冲突.

这使得程序员的生活变得更加容易,因为不必转义可能在LIKE子句中滑动并且不产生预期结果的所有特殊通配符.毕竟,=是99%的用例场景,每次都必须逃避它们是一件痛苦的事.

在90年代翻白眼

我也怀疑它有点慢,但我怀疑如果模式中没有通配符那么重要.



9> marc_s..:

如果搜索完全匹配,则可以同时使用=和LIKE.

在这种情况下使用"="会快一点(搜索完全匹配) - 您可以通过在SQL Server Management Studio中使用相同的查询两次来检查一次,一次使用"=",一次使用"LIKE",并且然后使用"查询"/"包括实际执行计划".

执行两个查询,您应该看到两次结果,再加上两个实际的执行计划.在我的情况下,他们被分为50%和50%,但"="执行计划有一个较小的"估计子树成本"(当你将鼠标悬停在最左边的"SELECT"框上时显示) - 但同样,它确实是没有太大的区别.

但是,当您在LIKE表达式中使用通配符开始搜索时,搜索性能将会变暗.搜索"LIKE Mill%"仍然可以非常快 - SQL Server可以在该列上使用索引(如果有的话).搜索"LIKE%expression%"的速度非常慢,因为SQL Server能够满足此搜索的唯一方法是进行全表扫描.所以要小心你的喜欢!



10> Laramie..:

为了解决有关性能的原始问题,它归结为索引利用率.当发生简单的表扫描时,"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

使用"="vs"LIKE"时,查询计划的创建可能会有微不足道的差异.

推荐阅读
N个小灰流_701
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有