web-dev-qa-db-fra.com

Remplacer plusieurs caractères d'une chaîne sans utiliser aucune fonction de remplacement imbriquée

J'ai une équation stockée dans ma table. Je vais chercher une équation à la fois et je veux remplacer tous les opérateurs par n'importe quel autre caractère. 

Chaîne d'entrée: (N_100-(6858)*(6858)*N_100/0_2)%N_35

Opérateurs ou modèles: (+, -, *, /, %, (, )) 

Caractère de remplacement: ~

Chaîne de sortie: ~N_100~~6858~~~6858~~N_100~0_2~~N_35

J'avais essayé la requête ci-dessous avec Nested REPLACE Functions et j'ai obtenu le résultat souhaité: 

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

Sortie: ~N_100~~6858~~~6858~~N_100~0_2~~N_35

Comment remplacer tous les opérateurs sans utiliser les fonctions de remplacement imbriquées?

6
Saharsh Shah

J'ai créé une fonction SPLIT pour l'implémenter car je dois implémenter cette opération plusieurs fois dans PROCEDURE

FONCTION SPLIT

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 utilisé dans la procédure:  

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

SORTIE

~N_100~~6858~~~6858~~N_100~0_2~~N_35
0
Saharsh Shah

Je crois que c'est plus facile et plus lisible si vous utilisez un tableau pour gérer cela. 

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
12
Shane Gebs

Il n'y a pas d'équivalent pour la fonction TRANSLATE d'Oracle dans SQL Server, vous devez utiliser des fonctions de remplacement imbriquées.

La solution suivante est techniquement correcte:

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;

Mais je ne vois pas pourquoi vous préféreriez cela aux appels imbriqués REPLACE.

5
Twinkles

Le moyen le plus simple consiste à utiliser la fonction TRANSLATE. Il est disponible à partir de SQL Server 2017 (aka vNext) et au-dessus.

TRANSLATE

Renvoie la chaîne fournie en tant que premier argument après que certains caractères spécifiés dans le second argument ont été traduits en un jeu de caractères de destination.

TRANSLATE ( inputString, characters, translations) 

Retourne une expression de caractère du même type que inputString où les caractères du deuxième argument sont remplacés par les caractères correspondants du troisième argument.

Dans ton cas:

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

DBFiddle Demo

1
Lukasz Szozda