Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
besserebrenik Member Откуда: Сообщений: 49 |
Есть столбец, в котором находиться xml с текстом, содержащий перенос строки CREATE TABLE Test ( Id INT IDENTITY(1, 1), Body XML, CONSTRAINT PK_Test PRIMARY KEY CLUSTERED (Id) ) INSERT INTO Test (Body) VALUES ('<Root><Value>Собака упала</Value></Root>') Я на данную таблицу повесил fulltext index CREATE FULLTEXT INDEX ON Test (Body LANGUAGE 1033) KEY INDEX PK_Test ON ProductFTS WITH STOPLIST = SYSTEM Данный запрос ничего не возвращает SELECT * FROM Test WHERE CONTAINS(Body, '"Собака упала"') Что странно, так как SELECT special_term, display_term FROM sys.dm_fts_parser (@Search1, 1033, 0, 0)с английским 1033 спокойно бъет строку на части игнорируя перенос. Что делал. Пытался создавать стоп-лист и туда писать '\r', '\n', '\r\n' (отнеся к этому скептически, но стоило попробовать), читал документацию на msdn, использовал поисковую систему (нашел это http://ask.sqlservercentral.com/questions/45304/sql-server-2008-line-break-and-fulltext-queries.html и аналогичный вопрос на codeproject), пробовал с русским языком 1049. Все равно перенос строки в xml не позволяет найти строку "собака упала" В данный момент придумал обходной путь, выглядевший так -- функция для сплита строки CREATE FUNCTION dbo.splitstring ( @stringToSplit VARCHAR(MAX) ) RETURNS @returnList TABLE ([Name] [nvarchar] (500)) AS BEGIN DECLARE @name NVARCHAR(255) DECLARE @pos INT WHILE CHARINDEX(' ', @stringToSplit) > 0 BEGIN SELECT @pos = CHARINDEX(' ', @stringToSplit) SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1) INSERT INTO @returnList SELECT @name SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos) END INSERT INTO @returnList SELECT @stringToSplit RETURN END -- А тут уже пример DECLARE @Search1 NVARCHAR(512) = 'Собака' + CHAR(13) + CHAR(10) + 'упала в 12:26:16 123 - #' DECLARE @SplitingString TABLE ( Word nvarchar(256) ) INSERT INTO @SplitingString ( Word ) SELECT * FROM splitstring(@Search1) DECLARE @Result NVARCHAR(512); -- Здесь будет строка формата 'собака NEAR упала NEAR в NEAR 12:26:16 NEAR 123' SELECT @Result = CASE WHEN @Result IS NULL THEN T.display_term ELSE @Result + ' NEAR ' + T.display_term END FROM ( SELECT * FROM @SplitingString SS INNER JOIN ( SELECT display_term FROM sys.dm_fts_parser('"' + @Search1 + '"', 1033, 0, 0) ) as Q ON Q.display_term = SS.Word ) AS T SELECT * FROM Test WHERE CONTAINS(Body, @Result) и это работает, но хотелось бы понять почему перенос строки заставляет писать костыли при поиске. Ведь пробелы и всякие символы, например, '-' или '#', а также стоп-слова (при наличии списка) игнорируются, а перенос строки и каретка нет. Кто нибудь сталкивался с переносом строки, работая с полнотекстовыми индексами? Как вы решили эту проблему? |
8 авг 14, 01:14 [16414926] Ответить | Цитировать Сообщить модератору |
besserebrenik Member Откуда: Сообщений: 49 |
Извиняюсь за плохое форматирование, переносил из SQL managment studio Для запроса выше необходимо создать каталог для полнотекстового поиска
CREATE FULLTEXT CATALOG ProductFTS
А теперь более удивительные вещи Такой код сработает ! CREATE TABLE Test2 ( Id INT IDENTITY(1, 1), Body VARCHAR(512), CONSTRAINT PK_Test2 PRIMARY KEY CLUSTERED (Id) ) INSERT INTO Test2 (Body) VALUES ('Собака упала') INSERT INTO Test2 (Body) VALUES ('Ушел' + CHAR(13) + CHAR(10) + 'паровоз') CREATE FULLTEXT INDEX ON Test2 ( Body LANGUAGE 1033 ) KEY INDEX PK_Test2 ON ProductFTS WITH STOPLIST = OFF SELECT * FROM Test2 WHERE Contains(Body, '"Собака упала"') -- Есть результат SELECT * FROM Test2 WHERE Contains(Body, '"Ушел паровоз"') -- Есть результат Разница вся только в том, что в первом случае столбец xml, а во втором текст Причем оба запроса возвращают абсолютно одинаковые токены! SELECT display_term, column_id, document_count FROM sys.dm_fts_index_keywords (DB_ID('Put your db name'), OBJECT_ID('Test')) SELECT display_term, column_id, document_count FROM sys.dm_fts_index_keywords (DB_ID('Put your db name'), OBJECT_ID('Test2')) |
8 авг 14, 01:31 [16414946] Ответить | Цитировать Сообщить модератору |
besserebrenik Member Откуда: Сообщений: 49 |
Для подтверждения того, что разница только в типе данных, еще раз прилагаю запрос чуть модифицированный. Те же данные, но тип xmlCREATE TABLE Test3 ( Id INT IDENTITY(1, 1), Body XML, CONSTRAINT PK_Test3 PRIMARY KEY CLUSTERED (Id) ) INSERT INTO Test3 (Body) VALUES ('Собака упала') INSERT INTO Test3 (Body) VALUES ('Ушел' + CHAR(13) + CHAR(10) + 'паровоз') CREATE FULLTEXT INDEX ON Test3 ( Body LANGUAGE 1033 ) KEY INDEX PK_Test3 ON ProductFTS WITH STOPLIST = OFF SELECT * FROM Test3 WHERE Contains(Body, '"Собака упала"') -- пусто SELECT * FROM Test3 WHERE Contains(Body, '"Ушел паровоз"') -- пусто |
8 авг 14, 01:37 [16414947] Ответить | Цитировать Сообщить модератору |
Winnipuh Member [заблокирован] Откуда: Київ Сообщений: 10428 |
какой хмл показывает запрос?SELECT * FROM Test |
8 авг 14, 11:28 [16416077] Ответить | Цитировать Сообщить модератору |
Winnipuh Member [заблокирован] Откуда: Київ Сообщений: 10428 |
А так?SELECT * FROM Test WHERE CONTAINS(Body, '"Собака" AND "упала"') |
8 авг 14, 11:30 [16416088] Ответить | Цитировать Сообщить модератору |
invm Member Откуда: Москва Сообщений: 9633 |
besserebrenik, можете вот так выкрутиться: CREATE TABLE Test3 ( Id INT IDENTITY(1, 1), Body XML, CONSTRAINT PK_Test3 PRIMARY KEY CLUSTERED (Id), BodyText as cast(Body as nvarchar(max)) ) INSERT INTO Test3 (Body) VALUES ('Собака упала') INSERT INTO Test3 (Body) VALUES ('Ушел' + CHAR(13) + CHAR(10) + 'паровоз') CREATE FULLTEXT INDEX ON Test3 ( BodyText LANGUAGE 1033 ) KEY INDEX PK_Test3 ON ProductFTS WITH STOPLIST = OFF SELECT * FROM Test3 WHERE Contains(BodyText, '"Собака упала"') -- пусто SELECT * FROM Test3 WHERE Contains(BodyText, '"Ушел паровоз"') -- пусто |
||
8 авг 14, 11:43 [16416196] Ответить | Цитировать Сообщить модератору |
Winnipuh Member [заблокирован] Откуда: Київ Сообщений: 10428 |
да, но интересен результат |
||
8 авг 14, 11:59 [16416333] Ответить | Цитировать Сообщить модератору |
invm Member Откуда: Москва Сообщений: 9633 |
|
||
8 авг 14, 12:01 [16416352] Ответить | Цитировать Сообщить модератору |
Winnipuh Member [заблокирован] Откуда: Київ Сообщений: 10428 |
ну, в общем случае - не факт. У меня, например, такой скрипт, как в первом сообщении дал такой результат <Root><Value>?????? ?????</Value></Root> |
||||
8 авг 14, 12:38 [16416659] Ответить | Цитировать Сообщить модератору |
invm Member Откуда: Москва Сообщений: 9633 |
|
||
8 авг 14, 13:48 [16417190] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |