如何在SQL Server中使用领先的通配符全文搜索?

时间:2008-08-06 13:52:29

标签: sql-server full-text-search

注意:使用SQL的全文搜索功能,CONTAINS子句和所有 - *是全文的通配符,%仅用于LIKE子句

我现在在几个地方读过MS SQL不支持“前导通配符”搜索(例如使用“* overflow”来匹配“stackoverflow”)。我正在考虑使用CLR function to add regex matching,但我很想知道人们可能会有哪些解决方案。

更多信息You can add the asterisk only at the end of the word or phrase. - 以及我的实验经验:匹配“myvalue”时,“my *”有效,但“(星号)值”返回时不匹配一个简单的查询:

SELECT * FROM TABLENAME WHERE CONTAINS(TextColumn, '"*searchterm"');

因此,我需要一种解决方法。我只在实际搜索页面上使用我的网站搜索 - 所以它的工作方式基本上与Google的工作方式相同(在Joe Sixpack类型的用户眼中)。不是那么复杂,但这种匹配真的不应该失败。

13 个答案:

答案 0 :(得分:22)

仅针对前导通配符的解决方法:

  • 将文本反转存储在不同的字段中(或在物化视图中)
  • 在此列上创建全文索引
  • 使用*

    查找反转文本
    SELECT * 
    FROM TABLENAME 
    WHERE CONTAINS(TextColumnREV, '"mrethcraes*"');
    

当然有许多缺点,只是为了快速解决方法......

更不用说CONTAINSTABLE ......

答案 1 :(得分:14)

领先通配符的问题:它们无法编入索引,因此您正在进行全表扫描。

答案 2 :(得分:6)

可以在单词或短语的末尾使用通配符“*”(前缀搜索)。

例如,此查询将找到所有“datab”,“database”,“databases”......

SELECT * FROM SomeTable WHERE CONTAINS(ColumnName, '"datab*"')

但是,不可思议的是,无法使用前导通配符进行搜索。

例如,此查询将找不到“数据库”

SELECT * FROM SomeTable WHERE CONTAINS(ColumnName, '"*abase"')

答案 3 :(得分:4)

或许为这个帖子添加清晰度,从我在2008 R2的测试中,Franjo在上面是正确的。在处理全文搜索时,至少在使用CONTAINS短语时,您不能在功能上使用前导,只能使用尾随。 *是通配符,而不是全文%。

有人建议忽略*。情况似乎并非如此,我的结果似乎表明尾随*功能确实有效。我认为领先*会被引擎忽略。

我添加的问题是,使用带有通配符的全文的同一查询在2005年(20秒)使用通配符的速度相对较快,并且在将数据库迁移到2008 R2后减慢到12分钟。似乎至少有一个其他用户有类似的结果,他开始了一个论坛帖子,我加入了...... FREETEXT仍然工作得很快,但“看起来”似乎已经改变了2008年处理尾随*在CONTAINS中的方式。他们在升级顾问中提供各种警告,他们“改进”了全文,因此您的代码可能会中断,但不幸的是,他们没有给您任何关于某些弃用代码等的特定警告......只是他们改变了它的免责声明,使用风险自负。

http://social.msdn.microsoft.com/Forums/ar-SA/sqlsearch/thread/7e45b7e4-2061-4c89-af68-febd668f346c

也许,这是与这些问题相关的最接近的MS点击... http://msdn.microsoft.com/en-us/library/ms143709.aspx

答案 4 :(得分:3)

值得记住的一点是,与其他通配符使用相比,领先的通配符查询具有显着的性能溢价。

答案 5 :(得分:2)

SQL Server中的通配符是%符号,它可以很好地工作,领先,尾随或其他方式。

那就是说,如果您要进行任何严肃的全文搜索,那么我会考虑使用全文索引功能。使用%_通配符会导致数据库严重受损。

答案 6 :(得分:1)

从SQL Server联机丛书:

  

写入全文查询   您必须使用Microsoft SQL Server 2005   学习如何使用CONTAINS和   FREETEXT Transact-SQL谓词和   CONTAINSTABLE和FREETEXTTABLE   行集值函数。

这意味着上面用%和_写的所有查询都不是有效的全文查询。

以下是调用CONTAINSTABLE函数时查询的示例。

  

SELECT RANK,* FROM TableName,   CONTAINSTABLE(TableName,*,'   “* WildCard”')searchTable WHERE     [KEY] = TableName.pk ORDER BY     searchTable.RANK DESC

为了让CONTAINSTABLE函数知道我正在使用通配符搜索,我必须用双引号将其包装起来。我可以在开头或结尾使用通配符*。当您为CONTAINSTABLE函数构建搜索字符串时,还可以执行许多其他操作。你可以搜索另一个单词附近的单词,搜索屈折单词(drive = drives,drive,driving和driven),并搜索另一个单词的同义词(metal可以有同义词,如铝和钢)。

我刚刚创建了一个表,在表上放了一个全文索引并进行了几次测试搜索并且没有问题,因此通配符搜索按预期工作。

[更新]

我看到你已经更新了你的问题并且知道你需要使用其中一个功能。

您仍然可以在开头使用通配符进行搜索,但如果该单词不是通配符后面的完整单词,则必须在末尾添加另一个通配符。

Example:  "*ildcar" will look for a single word as long as it ends with "ildcar".

Example:  "*ildcar*" will look for a single word with "ildcar" in the middle, which means it will match "wildcard".  [Just noticed that Markdown removed the wildcard characters from the beginning and ending of my quoted string here.]

[更新#2]

Dave Ward - 使用带有其中一个函数的通配符不应该是一个巨大的性能。如果我创建一个只有“*”的搜索字符串,它将不会返回所有行,在我的测试用例中,它返回了0条记录。

答案 7 :(得分:1)

仅供参考,Google不进行任何子字符串搜索或截断,向右或向左。他们有一个通配符*来查找短语中的未知单词,但不是单词。

Google与大多数全文搜索引擎一起,根据字母的字母顺序设置倒排索引,并提供指向源文档的链接。即使对于巨大的索引,二进制搜索也很快。但是在这种情况下进行左截断真的很难,因为它失去了索引的优势。

答案 8 :(得分:1)

作为存储过程中的参数,您可以将其用作:

useAsDefault

答案 9 :(得分:0)

说到全文搜索,我的钱没有什么比Lucene好。有一个.Net port available与使用Java版本创建的索引兼容。

您需要创建/维护索引,但是搜索速度非常快,您可以创建各种有趣的查询。即使索引速度也非常好 - 我们只需每天完成一次索引重建,不用担心更新它们。

例如,this search functionality由Lucene.Net提供支持。

答案 10 :(得分:0)

也许以下链接将为使用通配符提供最终答案:Performing FTS Wildcard Searches

请注意以下段落:"但是,如果指定“ Chain”或“Ch ain”,则无法获得预期结果。星号将被视为正常的标点符号,而不是通配符。 "

答案 11 :(得分:0)

如果您有权访问全文本搜索引擎的单词列表,则可以对此列表进行“喜欢”搜索,然后将数据库与找到的单词进行匹配,例如带有以下单词的表“ words”:     馅饼     苹果派     间谍     樱桃派     狗     猫 要将该数据库中所有包含“ pie”的单词与fts表“ full_text”上的字段“ text”进行匹配:     匹配<-从单词中选择单词,其中单词类似于'%pie%'     匹配者=“”     a =“”     foreach(m,要匹配){       匹配者+ = a       配对者+ = m       一个=“ OR”     }     从全文中选择文本,其中文本匹配匹配器

答案 12 :(得分:-1)

%匹配任意数量的字符     _匹配单个字符

我从未使用过全文索引,但只需使用T-SQL字符串函数中的构建就可以完成相当复杂和快速的搜索查询。