Амперсанд полнотекстового поиска SQL Server (&) - PullRequest
8 голосов
/ 10 октября 2011

есть проблемы с амперсандом (&)

Как искать слова (или предложения), содержащие амперсанд (&).

Например, в базе данных есть:

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

Как написать полнотекстовый поисковый запрос для поиска отдельных записей?

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

Я знаю, что символ (&) отвечает за логическую операцию И. Но я не знаю, как его кодировать для поиска по тексту с использованием полнотекстового поиска.

Есть идеи?

Ответы [ 2 ]

7 голосов
/ 10 октября 2011

Короткая версия: Вы не можете (или, по крайней мере, можете, но можете получить больше результатов, чем ожидали)

Длинная версия: Символ '&' рассматривается как «средство разбиения по словам», т. Е. Когда 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".

Это сделано специально, насколько я вижу, единственный способ изменить это поведение - установить собственный средство разбиения слов , однако я бы не рекомендовал это делать.

3 голосов
/ 23 сентября 2016

Принятый ответ не полностью правильный. Заключение поискового термина в двойные кавычки делает группировку слов совпадением «фразы». В этом случае амперсанд (&) может рассматриваться как буквенный символ, например, когда он окружен одной или несколькими буквами, которые не образуют известное слово. Просто глядя на ваш "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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...