我目前在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
任何帮助表示赞赏
非常感谢
答案 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'
*/