在MySQL中搜索“全字匹配”


75

我想编写一个SQL查询,该查询在文本字段中搜索关键字,但是仅当它是“全字匹配”时(例如,当我搜索“ rid”时,它不应该与“ arid”匹配,但是应该匹配“摆脱”。

我正在使用MySQL。

幸运的是,在该应用程序中性能并不是至关重要的,并且数据库大小和字符串大小都非常小,但是我更喜欢在SQL中而不是在驱动它的PHP中这样做。

Answers:


153

您可以使用REGEXP[[:<:]][[:>:]]字边界标记:

SELECT *
FROM table 
WHERE keywords REGEXP '[[:<:]]rid[[:>:]]'

2020年更新:(实际上是2018年以上)

MySQL在8.0.4版中更新了RegExp-Engine,因此您现在需要使用标准”字边界标记\ b:

SELECT *
FROM table 
WHERE keywords REGEXP '\\brid\\b'

另请注意,您需要通过放置第二个反斜杠来逃避反斜杠。


2
仅需注意,使用正则表达式特殊字符的字符串必须转义。
肯尼·崔

1
但是单词边界设置的另一个问题是,它可能会将句点视为单词边界,因此,如果要匹配名称,则它可能无法按预期工作。选择“ RC Sproul”正则表达式“ R \ .C \”。/ *返回1 * / ...选择'RC斯普劳尔'的regexp '[[:<:]] r \ .C \ [[:>:]]'/ *返回0 * /
Kenston彩

1
@LukeH-谢谢你。这太棒了。我使用过RLIKE,那么REGEX和RLIKE两者之间没有任何区别。
Shail Paras

1
对我有用。
Xcoder

2
只是在mysql查询中使用php变量的注释:'[[:<:]]" . $rid . "[[:>:]]'
stackunderflow

29

找到一个防止经典单词边界[[::<::]]与特殊字符冲突的答案,例如。@#$%^&*

更换..

SELECT *
FROM table 
WHERE keywords REGEXP '[[:<:]]rid[[:>:]]'

有了这个..

SELECT *
FROM table 
WHERE keywords REGEXP '([[:blank:][:punct:]]|^)rid([[:blank:][:punct:]]|$)'

后者匹配(空格,制表符等)|| (逗号,括号等)|| 行的开始/结束。更“完善”的单词边界匹配。


此代码对我不起作用。我得到:有Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''([[[:blank:][:punct:]]' at line 3 SQLState: 42000 ErrorCode: 1064想法吗?
Solver42 '16

@ Solver42我刚刚使用mysql 5.6.21重新测试了上面的查询,它正常工作。尝试从'([[[
Ricky Boyce

我试过了,但是遇到了同样的错误。但是,这起到了窍门:([[:blank:]] | [[:punct:]] ^^ rid([[:punct:]} | [[[:blank:]] | $)
Solver42

5

您可以使用like通配符标记来捕获各种可能性(在开始,结束,中间和单独出现时),如下所示就足够了:

选择blah blah bla'blah blah blagh blah where where column like'rid%'or column like'%rid'or column like'%rid%'or column ='rid'


根据情况,您还应注意标点符号。例如,这些都不会返回“ rid”。
格雷格·利弗

4
我认为查询还不够。诸如“ rid”或“(rid)”之类的文本呢?
强2010年

良好的答案,良好的观察力,简单的解决方案:您可以使用自定义行来定制查询以满足数据需求。例如,添加更多的线,如:or column like '% rid, %' or column like 'rid, %'。或使用上面的regex方法。
stackunderflow

4

将regexp与单词边界一起使用,但是如果您还希望对重音不敏感,则请注意REGEXP是单字节运算符,因此utf8_general_ci排序规则毫无意义,匹配不会对重音不敏感。

要使重音不区分大小写和整个单词都匹配,请以(不建议使用的)PHP函数sql_regcase()相同的方式指定编写的单词。

事实上:

  • utf8_general_ci允许您进行等号(WHERE字段=值)区分大小写和重音的搜索,但不允许您指定整个单词匹配(单词边界标记无法识别)

  • LIKE允许您区分大小写和重音的不敏感搜索,但您必须手动指定可能的单词边界特征的所有组合(无法识别单词边界标记)

  • REGEXP支持单词边界[[:<:]]和[[:>:]],后者是单字节函数,因此请勿执行不区分重音的搜索。

解决方案是将REGEXP与单词边界一起使用,并且按照sql_regcase的方式修改单词。

http://www.nonsolodiete.it上使用


1
select * from table where Locate('rid ', FieldToSearch) > 0 
      or Locate(' rid', FieldToSearch) > 0

这将处理查找在空格之前或之后的空格的问题,您可以扩展方法以考虑。,?!。等等,不是优雅但容易。


1

到目前为止,这是我自己得出的最佳答案:

SELECT * FROM table 
WHERE keywords REGEXP '^rid[ $]' OR keywords REGEXP ' rid[ $]'

我将其简化为:

SELECT *
FROM table
WHERE keywords REGEXP '[^ ]rid[ $]'

但是[^]的特殊含义是“不要有空格”,而不是“行首或空格”。

REGEXP与多个LIKE条件相比如何?(此应用程序的性能并不重要。)


2
如果您成功了[^],我认为第二个也可以。当^是集合IIRC中的第一个字符时,^仅是“ not”。
特拉维斯·詹森

我想知道SQL REGEXP是否具有像Perl \ b这样的“单词边界”字段?这将处理空格,标点符号等
安迪·怀特

@ Andy,MySql使用[[:<:]]和[[:>:]]作为单词边界标记。
路加福音

@Oddthinking,单词边界标记可能是您应该使用的标记。请参阅我的答案作为示例。
路加福音

1
或者,您也可以这样写:SELECT * FROM table WHERE关键字REGEXP'(^ |)rid(| $)'
Kenston Choi 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.