SQL Server全文搜索符号&

10

遇到&符号的问题

如何搜索包含&符号的单词或句子。

例如,在数据库中:

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

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

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

我知道字符(&)用于逻辑AND操作。但我不知道如何对其进行编码,以便在使用全文搜索的情况下进行搜索。有什么想法吗?

你好,@czarczarek。你是否愿意更改被接受的答案?我提出这个请求并不是因为另一个答案是我的,而是因为当前被接受的答案是错误的(正如我在我的回答中所解释的那样),这可能会对一些读者造成困惑/误导(他们可能不会查看其他答案并意识到他们确实可以解决这个问题)。谢谢。 - Solomon Rutzky
2个回答

7

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

详细版: 字符'&'被视为“断字器”,也就是说,当SQL Server遇到'&'时,它会将其视为新“单词”(例如标记)的开始。在解析"AT&T"时,SQL Server看到的是两个标记,分别是"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"几乎完全相同。
根据设计,我认为修改此行为的唯一方法是安装自己的分词器,但我不建议这样做。

5

被接受的答案并不全面正确。将搜索词用双引号括起来可以使单词组成一个“短语”匹配。在这种情况下,安帕ersand (&) 可以被视为字面字符,例如当周围有一个或多个不构成已知单词的字母时。只需看一下你的"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

1
这应该是被接受的答案。但是,考虑到现在已经过去了五年,这也是可以理解的。 - Jacob Stamm
@JacobStamm 谢谢!我不认为人们总是会收到新答案的通知。不确定。因此,我在问题下添加了一条评论,请求 O.P.(根据其个人资料仍然活跃)考虑更改采纳答案。 - Solomon Rutzky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接