Replace the alternate occurances of a substring
Here's a solution that uses a UDF.
The function splits a string on a pattern as a resultset.
(similar as the STRING_SPLIT function, but with a pattern)
The FOR XML
trick is then used to construct a string from the splitted parts, and to add the quotes.
DECLARE @vchNewValue VARCHAR(100), @result VARCHAR(100); SET @vchNewValue = 'A OR B or C OR D or E OR F'; SET @result = LTRIM(RTRIM(( SELECT CASE WHEN match = 1 THEN ' '+quotename(ltrim(rtrim(replace(value,' OR ',' or ') )),'''')+' ' ELSE UPPER(value) END FROM dbo.fnPattern_Split(' '+@vchNewValue+' ', ' % OR % ') AS spl ORDER BY ordinal FOR XML PATH(''), TYPE).value(N'./text()[1]', N'nvarchar(max)') )); SELECT @result AS result;
result |
---|
'A or B' OR 'C or D' OR 'E or F' |
Test db<>fiddle here
The UDF
Uses PATINDEX to find each next start position of the given pattern in the string.
Then finds the nearest end position where the pattern is still valid.
So it's kinda like a lazy search in regex.
The positions are then used to insert the parts into the returned table.
CREATE FUNCTION dbo.fnPattern_Split ( @str VARCHAR(MAX), @pattern VARCHAR(100) ) RETURNS @tbl TABLE ( ordinal INT, value VARCHAR(MAX), match BIT ) WITH SCHEMABINDING AS BEGIN DECLARE @value NVARCHAR(MAX) , @splitvalue NVARCHAR(MAX) , @startpos INT = 0 , @endpos INT = 0 , @ordinal INT = 0 , @foundend BIT = 0 , @patminlen INT = ISNULL(NULLIF(LEN(REPLACE(@pattern,'%','')),0),1); WHILE (LEN(@str) > 0) BEGIN SET @startpos = ISNULL(NULLIF(PATINDEX('%'+@pattern+'%', @str),0), LEN(@str)+1); IF @startpos < LEN(@str) BEGIN SET @foundend = 0; SET @endpos = @startpos+@patminlen-1; WHILE @endpos < LEN(@str) AND @foundend = 0 BEGIN IF SUBSTRING(@str, @startpos, 1+@endpos-@startpos) LIKE @pattern SET @foundend = 1; ELSE SET @endpos += 1; END END ELSE SET @endpos = LEN(@str); IF @startpos > 1 BEGIN SET @ordinal += 1; SET @value = LEFT(@str, @startpos-1); INSERT INTO @tbl (ordinal, value, match) VALUES (@ordinal, @value, 0); END IF @endpos >= @startpos BEGIN SET @ordinal += 1; SET @splitvalue = SUBSTRING(@str, @startpos, 1+@endpos-@startpos); INSERT INTO @tbl (ordinal, value, match) VALUES (@ordinal, @splitvalue, 1); END SET @str = SUBSTRING(@str, @endpos+1, LEN(@str)); END; RETURN; END;
A recursive solution that stuffs the quotes.
The recursive CTE loops through the string while finding the start positions of the ' or ' patterns.
Since ' or ' has 4 characters, having a start position means you also have the end position.
TheSTUFF
function can insert characters in a string on positions.
So the positions are used to stuff the quotes where needed.
Which is every even occurence (modulus 2 of lvl is 0).
declare @input varchar(100) , @result varchar(100); set @input = 'A OR B or C OR D or E OR F'; set @result = @input; with rcte as ( select 1 as lvl , charindex(' or ', @input) as pos , len(@input) as max_pos union all select lvl+1 , isnull(nullif(charindex(' or ', @input, pos+4), 0), max_pos) , max_pos from rcte where pos < max_pos ) select @result = stuff(stuff(@result,pos+4,0,''''),pos,0,'''') from rcte where lvl%2 = 0 and pos+4 < max_pos order by lvl desc; SET @result = ''''+@result+''''; SET @result = REPLACE(REPLACE(@result,' OR ',' or '),''' or ''',''' OR '''); select @result as result;
result |
---|
'A or B' OR 'C or D' OR 'E or F' |
Test on db<>fiddle here