49

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

我现在在几个地方读到 MS SQL 不支持“前导通配符”搜索(例如,使用“*overflow”来匹配“stackoverflow”)。我正在考虑使用CLR 函数来添加正则表达式匹配,但我很想知道人们可能有什么其他解决方案。

更多信息您只能在单词或短语的末尾添加星号。- 连同我的经验经验:当匹配“myvalue”时,“my*”有效,但“(星号)值”返回不匹配,当做一个简单的查询时:

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

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

4

13 回答 13

28

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

  • 将反转的文本存储在不同的字段中(或物化视图中)
  • 在该列上创建全文索引
  • 找到带有 * 的反转文本

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

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

更不用说 CONTAINSTABLE ...

于 2008-09-23T23:11:43.040 回答
16

前导通配符的问题:它们无法被索引,因此您正在执行全表扫描。

于 2008-08-06T14:07:59.973 回答
10

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

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

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

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

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

SELECT * FROM SomeTable WHERE CONTAINS(ColumnName, '"*abase"')
于 2008-11-26T09:22:02.710 回答
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

于 2011-10-06T18:17:56.623 回答
3

注意CONTAINS:这是我在修订版 #2 中引入关键字之前为问题的原始版本 #1 提交的答案。事实上,它仍然是准确的。

SQL Server 中的通配符是%符号,它可以正常工作,无论是前导、尾随还是其他。

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

于 2008-08-06T13:57:28.683 回答
3

值得记住的一件事是,与其他通配符用法相比,领先的通配符查询具有显着的性能优势。

于 2008-08-06T14:03:59.123 回答
1

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

谷歌与大多数全文搜索引擎一样,根据单词的字母顺序建立了一个倒排索引,并带有指向其源文档的链接。二进制搜索速度很快,即使对于巨大的索引也是如此。但是在这种情况下真的很难做到左截断,因为它失去了索引的优势。

于 2008-09-16T00:22:38.610 回答
1

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

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)
于 2016-01-04T23:59:40.290 回答
0

在全文搜索方面,对我而言,没有什么比Lucene更好的了。有一个可用的 .Net 端口与使用 Java 版本创建的索引兼容。

您必须创建/维护索引涉及一些工作,但搜索速度非常快,您可以创建各种有趣的查询。甚至索引速度也相当不错——我们每天只需完全重建一次索引,不用担心更新它们。

例如,此搜索功能由 Lucene.Net 提供支持。

于 2008-08-08T15:34:28.997 回答
0

如果您可以访问全文搜索引擎的单词列表,您可以在此列表上进行“喜欢”搜索,并将数据库与找到的单词匹配,例如带有以下单词的表“单词”:

    pie
    applepie
    spies
    cherrypie
    dog
    cat

要在 fts 表 'full_text' 上匹配此数据库中包含 'pie' 的所有单词,并带有字段 'text':

    to-match <- SELECT word FROM words WHERE word LIKE '%pie%'
    matcher = ""
    a = ""
    foreach(m, to-match) {
      matcher += a
      matcher += m
      a = " OR "
    }
    SELECT text FROM full_text WHERE text MATCH matcher
于 2018-07-02T14:20:02.597 回答
0

或许下面的链接将为这种通配符的使用提供最终答案:执行 FTS 通配符搜索

请注意以下段落:“但是,如果您指定“<em>Chain”或“Chain”,您将不会得到预期的结果。星号将被视为普通标点符号而不是通配符。“

于 2016-10-18T17:34:27.467 回答
-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 函数构建搜索字符串时,您还可以做很多其他事情。您可以搜索靠近另一个词的词,搜索屈折词(驱动 = 驱动器、驱动器、驾驶和驱动),以及搜索另一个词的同义词(金属可以有铝和钢等同义词)。

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

[更新]

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

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

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 条记录。

于 2008-08-06T15:08:11.130 回答
-1

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

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

于 2008-08-06T14:00:57.600 回答