#sql-server
#sql-server
Вопрос:
кто-нибудь понимает, почему я все еще получаю 0 в результате:
SELECT [KnowItAll].[dbo].[VSM_CanculateTermFrequency] (
'hello hi hello by hello why'
,'hi')
GO
Где VSM_CanculateTermFrequency:
CREATE FUNCTION [dbo].[VSM_CanculateTermFrequency]
(
@i_Document NCHAR(4000),
@i_Term NCHAR(30)
)
RETURNS SMALLINT
AS
BEGIN
-- Declare the return variable here
DECLARE @TermFrequency SMALLINT
DECLARE @pos INT
DECLARE @nextpos INT
SELECT @pos = 0, @nextpos = 1, @TermFrequency = 0
WHILE @nextpos > 0
BEGIN
SELECT @nextpos = CHARINDEX(@i_Term,@i_Document)
SELECT @TermFrequency = CASE
WHEN @nextpos > 0 THEN @TermFrequency 1
ELSE @TermFrequency
END
SELECT @pos = @nextpos
END
RETURN @TermFrequency
END
Ответ №1:
Проблема заключается в вашем использовании nchar
. По сути, вы не ищете 'hi'
, вы ищете
'hi '
Вам следует изменить тип данных для ваших двух параметров на nvarchar
. При использовании nchar
система дополняет значение пробелами, чтобы оно стало 30 или 4000 символов.
Кстати, другая проблема, которую я вижу, не связанная с тем, что CharIndex всегда возвращает нулевую проблему (что связано с заполнением), заключается в том, что вы не указываете CharIndex выполнять поиск после последнего найденного термина. Вы должны изменить свой вызов CharIndex на:
CHARINDEX(@i_Term,@i_Document,@pos 1)
(Кстати, я вижу, что Гейб нашел это первым)
Ответ №2:
Как только вы измените свой тип данных на nvarchar
, вы обнаружите, что у вас есть бесконечный цикл, потому что он всегда начинает поиск с начала документа. Ваша строка должна гласить:
SELECT @nextpos = CHARINDEX(@i_Term,@i_Document, @pos 1)
Комментарии:
1. Да, это я видел и исправил, но это не проблема