【问题标题】:SQL Server Full Text Search ampersand (&)SQL Server 全文搜索与符号 (&)
【发布时间】:2016-09-24 04:09:59
【问题描述】:

& 符号有问题

如何搜索包含与号 (&) 的单词(或句子)。

例如在数据库中有:

1: "Johnson & Johnson"
2: "AT&T"
3: "Sample & Sample"

我应该如何编写全文搜索查询来搜索单个记录?

SELECT * from Companies c WHERE CONTAINS(c.CompanyName, '"AT&T"')

我知道字符 (&) 负责逻辑与运算。但我不知道如何对其进行编码以使用全文搜索进行文本搜索。

有什么想法吗?

【问题讨论】:

  • 您好,@czarczarek。您是否愿意切换接受哪个答案?我没有问太多,因为另一个答案是我的,而是因为当前接受的答案是不正确的(正如我在我的回答中解释的那样),并且可能会混淆/误导一些读者将错误的答案作为接受的答案(他们可能不会看其他答案并意识到他们确实可以解决这个问题)。谢谢??????

标签: sql-server full-text-search ampersand


【解决方案1】:

短版:你不能(或者至少你可以,但你可能会得到比你预期更多的结果)

长版: 字符 '&' 被视为“断字”,即当 SQL Server 遇到 '&' 时,它会将其视为新“单词”的开始(即令牌)。 SQL Server 在解析 "AT&T" 时看到的是两个标记,"AT""T"

您可以使用sys.dm_fts_parser 自行检查:

SELECT * FROM sys.dm_fts_parser('AT&T', 1033, 0, 0)

keyword     group_id    phrase_id   occurrence  special_term  display_term  expansion_type source_term
----------- ----------- ----------- ----------- ------------- ------------- -------------- -----------
0x00610074  1           0           1           Noise Word    at            0              AT
0x0074      2           0           1           Noise Word    t             0              T

这意味着搜索"AT&T" 与搜索"AT T" 几乎完全相同。

这是设计使然,据我所知,修改此行为的唯一方法是安装您自己的 word breaker,但我不建议这样做。

【讨论】:

    【解决方案2】:

    接受的答案并不完全正确。将搜索词括在双引号中会使单词分组成为“短语”匹配。在这种情况下,与号 (&) 可以 被视为文字字符,例如当被一个或多个不构成已知单词的字母包围时。只需查看您的 "AT&T" 示例,我们就会看到:

    DECLARE @Term NVARCHAR(100);
    SET @Term = N'"AT&T"';
    
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, 0, 0);
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, 0, 1);
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, NULL, 0);
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, NULL, 1);
    GO
    

    返回:

    keyword             group  phrase  occurrence  special      display  expansion  source
                        id     id                  term         term     type       term
    0x0061007400260074  1      0       1           Exact Match  at&t     0          AT&T
    

    如您所见,与号完全没有问题,只要它包含在您已经在做的双引号 (") 中,哇哦!

    但是,对于 "Johnson & Johnson" 示例来说,这并不干净:

    DECLARE @Term NVARCHAR(100);
    SET @Term = N'"Johnson & Johnson"';
    
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, 0, 0);
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, 0, 1);
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, NULL, 0);
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, NULL, 1);
    GO
    

    返回:

    keyword                         group  phrase  occurrence  special      display  expansion  source
                                    id     id                  term         term     type       term
    0x006A006F0068006E0073006F006E  1      0       1           Exact Match  johnson  0          Johnson & Johnson
    0x006A006F0068006E0073006F006E  1      0       2           Exact Match  johnson  0          Johnson & Johnson
    

    这似乎也与搜索词 Johnson Johnson 匹配,这在技术上是不正确的。

    因此,除了用双引号括起来之外,您还可以将 & 符号转换为下划线 (_),其处理方式不同:

    DECLARE @Term NVARCHAR(100);
    SET @Term = N'"Johnson _ Johnson"';
    
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, 0, 0);
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, 0, 1);
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, NULL, 0);
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, NULL, 1);
    GO
    

    返回:

    keyword                         group  phrase  occurrence  special      display  expansion  source
                                    id     id                  term         term     type       term
    0x006A006F0068006E0073006F006E  1      0       1           Exact Match  johnson  0          Johnson _ Johnson
    0x005F                          1      0       2           Exact Match  _        0          Johnson _ Johnson
    0x006A006F0068006E0073006F006E  1      0       3           Exact Match  johnson  0          Johnson _ Johnson
    

    而且,这样做一个字符翻译似乎不会对原始 "AT&T" 搜索产生不利影响:

    DECLARE @Term NVARCHAR(100);
    SET @Term = N'"AT_T"';
    
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, 0, 0);
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, 0, 1);
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, NULL, 0);
    SELECT * FROM sys.dm_fts_parser(@Term, 1033, NULL, 1);
    

    返回:

    keyword             group  phrase  occurrence  special      display  expansion  source
                        id     id                  term         term     type       term
    0x00610074005F0074  1      0       1           Exact Match  at_t     0          AT_T
    

    【讨论】:

    • 这应该是公认的答案。但是,鉴于是五年后的事,事实并非如此是可以理解的。
    • @JacobStamm 谢谢!我不认为人们总是会收到新答案的通知。没有把握。因此,我在问题中添加了一条评论,要求 O.P.(根据他们的个人资料似乎仍然活跃)考虑切换接受。
    猜你喜欢
    • 2010-09-06
    • 2010-10-04
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    • 2011-10-01
    相关资源
    最近更新 更多