检查一段文本是否为波形符号,并确保它们相隔60个字符。如果没有在中间放置波浪号

时间:2016-05-23 12:25:01

标签: sql sql-server tsql

我目前在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 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

这是基于我的String Splitting功能,它具有非常好的性能。

这个功能应该非常有效,虽然很难理解(我已经添加了一些纪念,试图让它变得更容易)。

您可以轻松更改内部参数,例如@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'
*/