Проверьте фрагмент текста для tilde и убедитесь, что они разделены 60 символами. Если не поместить Тильду между

В настоящее время у меня есть функция в SQL, которая помещает Тильду каждые 60 символов , но в исходном тексте уже есть Тильда, поэтому, в основном, я хочу изменить, что если есть Тильда, а следующая Тильда находится под 60 символами, то перейдите к следующей Тильде. Если его более 60 символов, то только тогда поместите дополнительную Тильду.

Моя текущая функция выглядит как;

function [dbo].[AddTilde] (
@string varchar(max),
@count int
)
returns varchar(max)
as
begin
    declare @result varchar(max) = ''
    declare @token varchar(max) = ''

    while DATALENGTH(@string) > 0
    begin
        select @token = left(@string, @count) 
        select @string = REPLACE(@string, @token, '')
        select @result +=@token +case when DATALENGTH(@string)=0             then '' else '~' end
    end

    return @result
 end

Любая помощь оценена

большое спасибо

2 ответа

  1. DECLARE @string1 VARCHAR(max),
            @string2 VARCHAR(max) = '',
            @i1 INT,
            @i2 INT
    
    SET @string1 = '12345678901234567890~1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'
    
    WHILE LEN(@string1) > 0
        BEGIN
            SET @i1 = CHARINDEX('~',@string1)
                SET @i2 = @i1 - (ABS(@i1-60) + (@i1-60)) / 2 -- MINIMUM OF ~ LOCATION AND 60
            SET @i1 = LEN(@string1)
            IF  @i2 = 0 SET @i2 = @i1 - (ABS(@i1-60) + (@i1-60)) / 2 -- MINIMUM OF LENGTH OF @string1 LOCATION AND 60
            IF @i2 < 60
                BEGIN
                    SET @string2 = @string2 + LEFT(@string1,@i2)
                    SET @string1 = RIGHT(@string1,@i1-@i2)
                END
            ELSE
                BEGIN
                    SET @string2 = @string2 + LEFT(@string1,60) + '~'
                    SET @string1 = RIGHT(@string1,@i1-60)
                END
        END
    

    Результаты: 12345678901234567890~123456789012345678901234567890123456789012345678901234567890~1234567890123456789012345678901234567890

  2. Это основано на моей функции разбиения строки, которая имеет очень хорошую производительность.

    Эта функция должна быть достаточно эффективной, хотя и трудной для понимания (я добавил несколько комментариев, чтобы сделать ее проще).

    Вы можете легко изменить внутренние параметры, например @Delimitor может быть несколько символов

    Тестовые случаи включены в нижней части.

    ALTER FUNCTION [dbo].[AddTilde]
    (
        @String VARCHAR( MAX ),
        @Count INT
    )
    RETURNS VARCHAR(MAX)
    AS
    BEGIN
        DECLARE @CurrentPosition BIGINT, @NextDelimiterPosition BIGINT, @NextFixedPosition BIGINT, @NextPosition BIGINT,
            @DelimiterLength INT, @Delimiter VARCHAR( 5 ), @Result VARCHAR( MAX )
    
        -- Initialise
        SET @Delimiter = '~'
        SET @DelimiterLength = LEN( @Delimiter )
        SET @Result = ''
         -- Ensures we can terminate loop without using an extra IF condition, saves a few = 0 checks
        SET @String = @String + @Delimiter
        SET @CurrentPosition = 1 
        -- Check for next Tilde position
        SET @NextDelimiterPosition = CHARINDEX( @Delimiter, @String, @CurrentPosition ) 
        -- Initialise fixed increment position
        SET @NextFixedPosition = @Count
        -- Compare, which one is earlier and use that one. Handle cases where the next token begins with Tilde 
        SET @NextPosition = CASE WHEN @NextDelimiterPosition - @DelimiterLength > @NextFixedPosition THEN @NextFixedPosition ELSE @NextDelimiterPosition END
    
        WHILE @NextDelimiterPosition > 0
        BEGIN
            SET @Result = @Result + SUBSTRING( @String, @CurrentPosition, @NextPosition - @CurrentPosition + 1 )
                    -- Handle cases where the next token begins with Tilde and avoids doubling up Tildes
                    + ( CASE WHEN @NextPosition = @NextDelimiterPosition THEN '' ELSE @Delimiter END )
    
            SET @CurrentPosition = @NextPosition + 1
    
            -- Increment fixed position
            SET @NextFixedPosition = @CurrentPosition + @Count - 1
            -- Check for next Tilde position
            SET @NextDelimiterPosition = CHARINDEX( @Delimiter, @String, @CurrentPosition )
            SET @NextPosition = CASE WHEN @NextDelimiterPosition - @DelimiterLength > @NextFixedPosition THEN @NextFixedPosition ELSE @NextDelimiterPosition END
        END
    
        -- Remove trailing Tilde
        SET @Result = SUBSTRING( @Result, 1, LEN( @Result ) - @DelimiterLength )
    
        RETURN @Result
    END
    
    /* Test Cases
    SELECT dbo.[AddTilde]( 'ab~c~defghijkl~', 3 ) --> 'ab~c~def~ghi~jkl~'
    SELECT dbo.[AddTilde]( '~ab~c~defghijkl', 3 ) --> '~ab~c~def~ghi~jkl'
    SELECT dbo.[AddTilde]( 'ab~c~~defghijkl', 3 ) --> 'ab~c~~def~ghi~jkl'
    SELECT dbo.[AddTilde]( 'abcdefghijkl', 3 )    --> 'abc~def~ghi~jkl'
    SELECT dbo.[AddTilde]( 'a', 3 )               --> 'a'
    */