CHARINDEX продолжает возвращать 0

#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. Да, это я видел и исправил, но это не проблема