如何让领先的通配符全文search在SQL Server中工作?

注意:正在使用SQL的全文searchfunction,CONTAINS子句和全部 – 全文是通配符,%仅用于LIKE子句。

我已经读过几个地方,现在在MS SQL中不支持“领先的通配符”search(例如使用“* overflow”来匹配“stackoverflow”)。 我正在考虑使用CLR函数来添加正则expression式匹配 ,但我很好奇,看看人们可能有什么其他解决scheme。

更多信息 : 只能在单词或短语的末尾添加星号。 – 与我的实证经验一起:当匹配“myvalue”,“my *”工作,但“(星号)值”返回不匹配时,执行如下简单的查询:

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

因此,我需要一个解决方法。 我只是在实际的search页面上使用我的网站进行search – 所以它需要基本上与Google的工作方式一样(在Joe Sixpacktypes的用户眼中)。 不是那么复杂,但是这种比赛真的不应该失败。

解决方法只适用于领先的通配符:

  • 将反转的文本存储在不同的字段(或物化视图中)
  • 在这个列上创build一个全文索引
  • find与*

     SELECT * FROM TABLENAME WHERE CONTAINS(TextColumnREV, '"mrethcraes*"'); 

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

CONTAINSTABLE更不用提…

领先的通配符的问题:他们不能被索引,因此你正在做一个全表扫描。

为了增加这个线程的清晰度,从我在2008 R2的testing中,Franjo是正确的。 在处理全文search时,至less在使用CONTAINS短语时,不能使用前导function,只能使用尾随function。 *是通配符,不是全文中的%。

有人build议*忽略。 这似乎并不是这样,我的结果似乎表明尾部*function确实工作。 我认为领先*被引擎忽略。

然而,我添加的问题是,在2005年(20秒)使用带有通配符的全文的相同查询,尾随*,在将数据库迁移到2008 R2后,速度减慢到12分钟。 似乎至less有一个其他用户有类似的结果,他开始了一个论坛post,我补充说… 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

值得一提的是,与其他通配符相比,领先的通配符查询具有显着的性能优势。

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

例如,这个查询将查找所有的“数据库”,“数据库”,“数据库”…

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

但是,毫无疑问,用领先的通配符search是不可能的。

例如,这个查询不会find“数据库”

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

在SQL Server中的通配符是%符号,它工作得很好,领先,尾随或其他。

这就是说,如果你要做任何一种严肃的全文search,那么我会考虑使用全文索引function。 使用%_通配符会导致数据库出现严重的性能%

从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函数知道我正在使用通配符search,我必须用双引号把它包装起来。 我可以在开头或结尾使用通配符*。 在为CONTAINSTABLE函数构buildsearchstring时,还可以执行其他许多操作。 你可以search另一个单词旁边的单词,search屈折词(驱动器=驱动器,驾驶,驾驶和驾驶),并search另一个词的同义词(金属可以具有铝和钢的同义词)。

我刚刚创build了一个表格,在表格上放了一个全文索引,并做了一些testingsearch,没有问题,所以通配符search就像预期的那样工作。

[更新]

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

您仍然可以在开头search通配符,但是如果单词不是通配符后面的整个单词,则必须在末尾添加另一个通配符。

 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 – 使用通配符和其中一个函数不应该是一个巨大的perf命中。 如果我用“*”创build了一个searchstring,它将不会返回所有行,在我的testing用例中,它返回了0条logging。

只是供参考,谷歌不做任何子stringsearch或截断,正确或左侧。 他们有一个通配符*来查找短语中的未知单词,而不是一个单词。

Google和大多数全文search引擎一起,根据字母的字母顺序build立一个倒排索引,并链接到它们的源文档。 二进制search速度很快,即使是巨大的索引。 但在这种情况下真的很难做左截断,因为失去了索引的优势。

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

 ALTER procedure [dbo].[uspLkp_DrugProductSelectAllByName] ( @PROPRIETARY_NAME varchar(10) ) as set nocount on declare @PROPRIETARY_NAME2 varchar(10) = '"' + @PROPRIETARY_NAME + '*"' select ldp.*, lkp.DRUG_PKG_ID from Lkp_DrugProduct ldp left outer join Lkp_DrugPackage lkp on ldp.DRUG_PROD_ID = lkp.DRUG_PROD_ID where contains(ldp.PROPRIETARY_NAME, @PROPRIETARY_NAME2) 

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

我从来没有使用全文索引,但你可以完成相当复杂和快速的search查询,只需使用T-SQLstring函数中的构build。

说到全文search,我的钱没有什么比击败Lucene 。 有一个.Net端口可用 ,与用Java版本创build的索引兼容。

有一点涉及到,你必须创build/维护索引,但search速度是太棒了,你可以创build各种有趣的查询。 即使索引速度是相当不错的 – 我们只是每天一次完全重build索​​引,而不必担心更新索引。

作为一个例子, 这个searchfunction由Lucene.Net提供支持。

也许下面的链接将提供通配符使用的最终答案: 执行FTS通配符search 。

请注意这段话:“但是,如果指定” 链“或”链接 “,则不会得到预期的结果。星号将被视为正常的标点符号而不是通配符。

使用“%”字符,我使用类似下面的内容search我们的数据库:

 SELECT name FROM TblNames WHERE name LIKE '%overflow' 

使用这种forms或查询可能有时慢,但我们只用于偶尔的手动search。