在SQL Server LIKE模式中搜索“全词匹配”

42

有没有人有一个只匹配整个单词的LIKE模式?

它需要考虑空格、标点符号以及字符串开头/结尾作为单词边界。

我没有使用SQL全文搜索因为那不可用。当LIKE应该能够完成简单的关键字搜索时,我不认为这是必要的。但是如果有人已经对全文搜索和LIKE模式进行了性能测试,我会很感兴趣听听。

编辑:

我已经将其调整到这个阶段,但它不会将字符串的开头和结尾作为单词边界匹配。

where DealTitle like '%[^a-zA-Z]pit[^a-zA-Z]%' 
我希望这可以匹配句子或单词中的“pit”,但不匹配“spit”。
例如,DealTitle可能包含“a pit of despair”、“pit your wits”、“a pit”、“a pit.”、“pit!”或仅为“pit”。

2
如果你不知道如何完成你需要完成的任务,你怎么能说LIKE应该能够解决问题呢? - Lasse V. Karlsen
1
你应该使用全文搜索来完成这个任务。如果真的不可用(为什么呢?它甚至随Express和Advanced Services一起提供),CLR和正则表达式会比LIKE更适合。 - Martin Smith
全文搜索为什么比LIKE更好?它更快吗?还是您认为使用LIKE无法完成整个单词的搜索? - mike nelson
1
全文搜索带有一个单词分解器,可以将文本分解并进行预索引。使用前导通配符的 LIKE 将始终涉及对所有数据的完整扫描。 - Martin Smith
即使在句子中,像“pit5”或“3pit”这样的情况怎么办? '%[^a-z]pit[^a-z]%'将允许它们出现,而你似乎并不打算这样做。 - Helen Craigman
9个回答

55

全文索引是答案。

较差的替代方案是

'.' + column + '.' LIKE '%[^a-z]pit[^a-z]%'

提示:除非使用_CS排序规则,否则无需使用a-zA-Z


太棒了。思路不错。我不想使用全文索引的原因是我不能依赖该选项被打开。它真的更好吗? - mike nelson
我该怎么说呢?..是的,是的,是的!(大部分时间都是这样)。简单来说,FTE将文本列分成单词,并单独对每个单词进行索引。(普通索引只会将一个记录放入索引一次)因此,如果单词“pit”在100万条记录中出现了99次,那么它就像普通索引一样好,可以识别出100万条记录中的99条记录(而无需执行任何模式匹配),而不是扫描所有记录并对每条记录执行完整的字符串长度比较(类似于LIKE操作)。就是这么好。 - RichardTheKiwi
2
好的,我已经在一个有11,000行的表上进行了测试,搜索两个列中的三个关键字。使用全文索引CONTAINS((col1,col2), 'keyword1 AND keyword2 AND keyword3')只需15毫秒,而使用LIKE模式(带有三个AND和三个OR)则需要350毫秒。因此,使用全文索引要快大约25倍。然而,考虑到它正在进行全表扫描,LIKE仍然似乎相当高效,因此在某些情况下这肯定是足够的-这取决于用户数量。 - mike nelson
全文搜索并不等同于在单词边界上进行搜索。在许多情况下,您可能想要搜索确切的文本片段(就像在Google上用双引号括起来一样),并且尊重单词边界。包含和FREETEXT对单词执行许多操作(如词干提取),但在某些情况下可能不是理想的选择。 - Marco Marsala
2
关于 .(点)字符的解释:[^a-z] 部分需要精确匹配一个字符。因此,空字符将不会匹配。例如,OP 的 LIKE 将不会匹配 'pit'、' pit' 或 'pit '。通过添加点,[^a-z] 部分与这些点匹配。 - anar khalilov
显示剩余3条评论

7
您可以使用以下条件来处理空格分隔符:
(' '+YOUR_FIELD_NAME+' ') like '% doc %'

它比其他解决方案更快、更好。所以在你的情况下,它可以很好地与 "a pit of despair" 或 "pit your wits" 或 "a pit" 或 "a pit." 或只是 "pit" 搭配使用,但不能用于 "pit!"。


5

我认为推荐的模式排除了开头或结尾没有任何字符的单词。我会使用以下附加条件。

where DealTitle like '%[^a-z]pit[^a-z]%' OR 
  DealTitle like 'pit[^a-z]%' OR 
  DealTitle like '%[^a-z]pit'

希望这对你们有所帮助!


2
不涉及完全相等于“pit”的处理。 - Cœur

3

在字符串前后加上空格,并创建一个类似下面的测试列:

 SELECT t.DealTitle 
 FROM yourtable t
 CROSS APPLY (SELECT testDeal = ' ' + ISNULL(t.DealTitle,'') + ' ') fx1
 WHERE fx1.testDeal LIKE '%[^a-z]pit[^a-z]%'

2
如果您可以在SQL查询中使用regexp运算符...
为了找到任何空格、标点和字符串开头/结尾的组合作为单词边界:
where DealTitle regexp '(^|[[:punct:]]|[[:space:]])pit([[:space:]]|[[:punct:]]|$)'

1
另一个简单的选择:
WHERE DealTitle like '%[^a-z]pit[^a-z]%' OR 
      DealTitle like '[^a-z]pit[^a-z]%' OR 
      DealTitle like '%[^a-z]pit[^a-z]'

1
不涉及完全相等于“坑”的处理 - Cœur
尝试使用以下代码:WHERE DealTitle like '%[^a-z]pit[^a-z]%' OR DealTitle like 'pit[^a-z]%' OR DealTitle like '%[^a-z]pit' - ssabbattini

1
这是一个很好的话题,我想向需要通过查询将某个单词传递为字符串元素来查找的人进行补充。
SELECT 
    ST.WORD, ND.TEXT_STRING
FROM 
    [ST_TABLE] ST
LEFT JOIN 
    [ND_TABLE] ND ON ND.TEXT_STRING LIKE '%[^a-z]' + ST.WORD + '[^a-z]%'
WHERE 
    ST.WORD = 'STACK_OVERFLOW' -- OPTIONAL

使用此功能,您可以列出所有ST.WORDND.TEXT_STRING中的出现情况,并且您可以使用WHERE子句来过滤使用某些单词。


0

你可以在 SQL 中搜索整个字符串:

select * from YourTable where col1 like '%TheWord%'

然后您可以在客户端过滤返回的行,添加额外的条件,即它必须是一个完整的单词。例如,如果它与正则表达式匹配:

\bTheWord\b

另一种选择是使用在SQL Server 2005及更高版本中可用的CLR函数。这将允许您在服务器端搜索正则表达式。这篇MSDN文章详细介绍了如何设置dbo.RegexMatch函数。

0

尝试使用charindex查找匹配项:

Select * 
from table 
where charindex( 'Whole word to be searched', columnname) > 0

1
那不是一个完整的单词搜索。那仍然是一个部分单词搜索。 - Fandango68

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接