6

I have an equation stored in my table. I am fetching one equation at a time and want to replace all the operators with any other character.

Input String: (N_100-(6858)*(6858)*N_100/0_2)%N_35

Operators or patterns: (+, -, *, /, %, (, ))

Replacement character: ~

Output String: ~N_100~~6858~~~6858~~N_100~0_2~~N_35

I had tried below query with Nested REPLACE Functions and I got desired output:

DECLARE @NEWSTRING VARCHAR(100) 
SET @NEWSTRING = '(N_100-(6858)*(6858)*N_100/0_2)%N_35' ;
SELECT @NEWSTRING = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
                    @NEWSTRING, '+', '~'), '-', '~'), '*', '~'), '/', '~')
                   , '%', '~'), '(', '~'), ')', '~')
PRINT @NEWSTRING

Output: ~N_100~~6858~~~6858~~N_100~0_2~~N_35

How can I replace all the operators without using nested replace functions?

2
  • Why what is wrong with Multiple Replce functions ? Commented Nov 7, 2013 at 12:07
  • I have some other operators also and I have to write Replace function multiple times. So I am finding alternate way to do this. Commented Nov 7, 2013 at 12:14

5 Answers 5

12

I believe it is easier and more readable if you use a table to drive this.

declare @String varchar(max) = '(N_100-(6858)*(6858)*N_100/0_2)%N_35'

--table containing values to be replaced
create table #Replace 
(
    StringToReplace varchar(100) not null primary key clustered
    ,ReplacementString varchar(100) not null    
)

insert into #Replace (StringToReplace, ReplacementString)
values ('+', '~')
    ,('-', '~')
    ,('*', '~')
    ,('/', '~')
    ,('%', '~')
    ,('(', '~')
    ,(')', '~')

select @String = replace(@String, StringToReplace, ReplacementString)
from #Replace a

select @String

drop table #Replace
Sign up to request clarification or add additional context in comments.

4 Comments

This is definitely better than using a split function (and a horribly inefficient one at that) to spit out a table dynamically. It is also 1000 times better than a while loop using a WHILE loop and PATINDEX :). +1
@srutzky OR Shane Gebs, if you're out there -- I'd love to have something like this (running on a field from each row of a table variable rather than a scalar), but for some reason, it is only replacing the first pair of values (first row) of #Replace (?) ---- that is, I've got letter pairs ('a', '+a'), ('b','+b'),('c'...etc and it's replacing all occurrences of a in the field of each row with +a, but not the b or c, etc replacements (?)
@CodeJockey Create a new question, reference this answer, and show what your current code is and the data you are trying to manipulate. Then post a link to that question here and I will answer it.
@SolomonRutzky Hey ! I am trying to do exactly what CodeJockey asked for. Would you mind take a look at this question? stackoverflow.com/questions/45800289
5

There is not equivalent for the TRANSLATE function from Oracle in SQL Server, you have to use nested replace functions.

The following solution is technically correct:

DECLARE @newstring VARCHAR(100) = '(N_100-(6858)*(6858)*N_100/0_2)%N_35';
DECLARE @pattern VARCHAR(100) = '%[+-\*/%()]%';
DECLARE @i INT;
BEGIN
  SET @i = PATINDEX(@pattern,@newstring) 
  WHILE @i <> 0
  BEGIN
    SET @newstring = LEFT(@newstring,@i-1) + '~' + SUBSTRING(@newstring,@i+1,100);
    SET @i = PATINDEX(@pattern,@newstring) 
  END
  SELECT @newstring;
END;

But I do not see why you would favor this over nested REPLACE calls.

1 Comment

I want alternative to do this operation.
2

The easiest way is to use TRANSLATE function. It is availble from SQL Server 2017 (aka vNext) and above.

TRANSLATE

Returns the string provided as a first argument after some characters specified in the second argument are translated into a destination set of characters.

TRANSLATE ( inputString, characters, translations) 

Returns a character expression of the same type as inputString where characters from the second argument are replaced with the matching characters from third argument.

In your case:

SELECT TRANSLATE('(N_100-(6858)*(6858)*N_100/0_2)%N_35', '+-*/%()','~~~~~~~')

DBFiddle Demo

Comments

0

I had created a SPLIT function to implement this because I need to implement this operation multiple time in PROCEDURE

SPLIT FUNCTION

create function [dbo].[Split](@String varchar(8000), @Delimiter char(1))       
returns @temptable TABLE (items varchar(8000))       
as       
begin       
    declare @idx int       
    declare @slice varchar(8000)       

    select @idx = 1       
        if len(@String)<1 or @String is null  return       

    while @idx!= 0       
    begin       
        set @idx = charindex(@Delimiter,@String)       
        if @idx!=0       
            set @slice = left(@String,@idx - 1)       
        else       
            set @slice = @String       

        if(len(@slice)>0)  
            insert into @temptable(Items) values(@slice)       

        set @String = right(@String,len(@String) - @idx)       
        if len(@String) = 0 break       
    end   
return       
end

Code used in procedure:

DECLARE @NEWSTRING VARCHAR(100) 
SET @NEWSTRING = '(N_100-(6858)*(6858)*N_100/0_2)%N_35' ;
SELECT @NEWSTRING = REPLACE(@NEWSTRING, items, '~') FROM dbo.Split('+,-,*,/,%,(,)', ',');
PRINT @NEWSTRING

OUTPUT

~N_100~~6858~~~6858~~N_100~0_2~~N_35

5 Comments

This is no need for a split function. The only purpose it is serving is to dynamically spit out a table. Since the replacement characters are a small, finite set, it is much much better to just create a temp table as shown in @Shane's answer. Also, there are many ways to accomplish a string split in T-SQL, and you have chosen the slowest. Please look into a SQLCLR-based splitter (you can get for free via SQL# (which I am the creator of but String_Split is in the Free version) or, at the very least, an XML-based splitter.
@srutzky Thank for your comment but I have to apply some business login on splitted values so I had used SPLIT function to split the values. So every time I can't use temporary table.
Ok about using split vs temp table. But, I am also saying to not use that split function. Split functions based on WHILE loops are horribly inefficient. There are several better choices.
@srutzky Can you provide me the other way to write split function
I provided a link in my first comment to a free SQLCLR splitter. Or you can search the web for examples if you want to write your own.
0

you can replace all the operators without using nested replace functions

DECLARE @Pattern VARCHAR(300) ='%[+-\*/%()]%';
DECLARE @String VARCHAR(300) ='(N_100-(6858)*(6858)*N_100/0_2)%N_35';
WHILE PatIndex(@Pattern, @String) <> 0
    SELECT @String=Replace(@String, Substring(@String, PatIndex(@Pattern, @String), 1), '~')
SELECT @String 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.