如何使领先的通配符全文本搜索在SQL Server中起作用?
注意:我正在使用SQL的全文本搜索功能,CONTAINS子句,并且所有*是全文本的通配符,%仅用于LIKE子句。
我现在已经在多个地方阅读过,MS SQL不支持"前导通配符"搜索(例如,使用" * overflow"来匹配" stackoverflow")。我正在考虑使用CLR函数添加正则表达式匹配,但是我很好奇人们可能还会有其他解决方案。
更多信息:我们只能在单词或者短语的末尾添加星号。以及我的经验:匹配" myvalue"时," my *"有效,但是执行以下查询时,"(星号)value"不返回匹配项:
SELECT * FROM TABLENAME WHERE CONTAINS(TextColumn, '"*searchterm"');
因此,我需要一种解决方法。我只在网站上的实际搜索页面上使用搜索,因此它的工作方式基本上与Google的工作方式相同(在Joe Sixpack类型的用户看来)。几乎没有那么复杂,但是这种匹配确实不应该失败。
解决方案
回答
SQL Server中的通配符是'%`符号,它可以正常工作,开头,结尾或者其他形式。
就是说,如果我们打算进行任何认真的全文搜索,那么我将考虑利用全文索引功能。使用%
和_
通配符将使数据库受到严重的性能影响。
回答
%匹配任意数量的字符
_匹配单个字符
我从未使用过全文索引,但是我们只需使用内置的T-SQL字符串函数就可以完成相当复杂和快速的搜索查询。
回答
值得记住的一件事是,与其他通配符用法相比,领先的通配符查询在性能上有显着提高。
回答
前导通配符的问题:无法对其进行索引,因此我们要进行全表扫描。
回答
使用'%'字符,我已经使用以下内容搜索了我们的数据库:
SELECT name FROM TblNames WHERE name LIKE '%overflow'
使用此表格或者查询有时可能会很慢,但我们仅将其用于偶尔的手动搜索。
回答
从SQL Server联机丛书中:
To write full-text queries in Microsoft SQL Server 2005, you must learn how to use the CONTAINS and FREETEXT Transact-SQL predicates, and the CONTAINSTABLE and FREETEXTTABLE rowset-valued functions.
这意味着上面用%和_编写的所有查询都不是有效的全文查询。
这是调用CONTAINSTABLE函数时查询的示例。
SELECT RANK , * FROM TableName , CONTAINSTABLE (TableName, *, ' "*WildCard" ') searchTable WHERE [KEY] = TableName.pk ORDER BY searchTable.RANK DESC
为了使CONTAINSTABLE函数知道我正在使用通配符搜索,我必须将其用双引号引起来。我可以在开头或者结尾使用通配符*。为CONTAINSTABLE函数构建搜索字符串时,我们可以执行许多其他操作。我们可以在另一个词附近搜索一个词,搜索变形词(驱动=驱动,驱动,驱动和从动),并搜索另一个词的同义词(金属可以具有铝和钢之类的同义词)。
我刚刚创建了一个表,在该表上放置了全文本索引,并进行了几次测试搜索,没有出现问题,因此通配符搜索可以按预期进行。
[更新]
我看到我们已经更新了问题,并且知道我们需要使用其中一个功能。
我们仍然可以在开头使用通配符进行搜索,但是如果单词不是通配符后的完整单词,则必须在末尾添加另一个通配符。
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条记录。
回答
在全文搜索方面,对于我的钱来说,Lucene是无与伦比的。有可用的.Net端口与Java版本创建的索引兼容。
我们必须创建/维护索引,这需要花点时间,但是搜索速度非常快,并且我们可以创建各种有趣的查询。即使索引速度非常好,我们每天也要完全重建一次索引,不必担心会更新它们。
例如,此搜索功能由Lucene.Net提供支持。
回答
仅供参考,Google不会左右进行任何子字符串搜索或者截断。它们具有通配符*,可以在短语中找到未知单词,但不能找到单词。
Google与大多数全文搜索引擎一起,根据单词的字母顺序设置了反向索引,并提供了指向其原始文档的链接。二进制搜索的速度很快,即使对于巨大的索引也是如此。但是在这种情况下,实际上很难进行左截断,因为它失去了索引的优势。
回答
解决方法仅适用于领先的通配符:
- 将反转的文本存储在其他字段(或者实体化视图)中
- 在此列上创建全文本索引
- 查找带有*的反向文本
SELECT * FROM TABLENAME WHERE CONTAINS(TextColumnREV, '"mrethcraes*"');
当然,有很多缺点,只是为了快速解决...
更不用说CONTAINSTABLE了...
回答
单词或者短语的末尾可以使用通配符" *"(前缀搜索)。
例如,此查询将找到所有"数据库","数据库","数据库" ...
SELECT * FROM SomeTable WHERE CONTAINS(ColumnName, '"datab*"')
但是,不幸的是,无法使用前导通配符进行搜索。
例如,此查询将找不到"数据库"
SELECT * FROM SomeTable WHERE CONTAINS(ColumnName, '"*abase"')