相关文章推荐
精明的针织衫  ·  如何使用Gson ...·  1 周前    · 
力能扛鼎的筷子  ·  Android ...·  1 年前    · 

替换字符串中的多个字符,无需使用任何嵌套替换函数

6 人关注

我有一个方程存储在我的表中。我一次取一个方程,想用任何其他字符替换所有的运算符。

输入字符串。 (N_100-(6858)*(6858)*N_100/0_2)%N_35

操作符或模式。 (+, -, *, /, %, (, ))

替换字符。 ~

输出字符串。 ~N_100~~6858~~~6858~~N_100~0_2~~N_35

我试着用 嵌套的REPLACE 函数做了以下查询,我得到了想要的输出。

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

输出。 ~N_100~~6858~~~6858~~N_100~0_2~~N_35

我怎样才能在不使用嵌套替换函数的情况下替换所有的操作符?

2 个评论
为什么多个Replce函数有什么问题?
我还有一些其他的运算符,我必须多次编写替换函数。所以我正在寻找其他的方法。
sql
sql-server
sql-server-2008
tsql
replace
Saharsh Shah
Saharsh Shah
发布于 2013-11-07
5 个回答
Shane Gebs
Shane Gebs
发布于 2019-11-21
0 人赞同

我相信如果你用一个表格来驱动,会更容易、更有可读性。

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
    
这绝对比使用分割函数(而且是效率低得可怕的函数)来动态地吐出一个表要好。这也比使用WHILE循环和PATINDEX的while循环好1000倍:)。+1
@srutzky OR Shane Gebs, 如果你在的话 -- 我很想拥有这样的东西(在一个表格变量的每一行的字段上运行,而不是一个标量),但是由于某些原因,它只替换#Replace (?) ---- 的第一对值(第一行),也就是说,我有字母对 ('a', '+a'), ('b','+b'),('c' ...等,它用 +a 替换每一行字段中所有出现的 a ,但是没有替换 b c 等(?)
@CodeJockey 创建一个新的问题,参考这个答案,并展示你当前的代码和你试图操作的数据。然后在这里发布该问题的链接,我会回答。
@SolomonRutzky 嘿!我想做的正是CodeJockey要求的事情。你介意看一下这个问题吗? stackoverflow.com/questions/45800289
Twinkles
Twinkles
发布于 2019-11-21
0 人赞同

在SQL Server中没有相当于Oracle的TRANSLATE函数,你必须使用嵌套的替换函数。

下面的解决方案 在技术上 是正确的。

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) 
  SELECT @newstring;
END;

但是我不明白为什么你会偏爱这个而不是嵌套的REPLACE调用。

我想让替代者来做这个手术。
Lukasz Szozda
Lukasz Szozda
发布于 2019-11-21
0 人赞同

最简单的方法是使用 TRANSLATE 功能。它可以从 SQL Server 2017 (aka vNext) 及以上版本获得。

TRANSLATE

在第二个参数中指定的一些字符被翻译成目标字符集后,返回作为第一个参数提供的字符串。

TRANSLATE ( inputString, characters, translations) 
  

返回一个与inputString相同类型的字符表达式,其中第二个参数中的字符被第三个参数中的匹配字符替换。

在你的例子中。

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

DBFiddle演示

Saharsh Shah
Saharsh Shah
发布于 2019-11-21
已采纳
0 人赞同

我创建了一个 SPLIT 函数来实现这一点,因为我需要在以下方面多次实现这一操作 PROCEDURE

SPLIT FUNCTION

create function [dbo].[Split](@String varchar(8000), @Delimiter char(1))       
returns @temptable TABLE (items varchar(8000))       
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)       
            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       
return       

程序中使用的代码。

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
    
这不需要一个分割函数。它的唯一作用是动态地吐出一个表。由于替换的字符是一个小的、有限的集合,如@Shane的回答中所示,直接创建一个临时表要好得多。另外,在T-SQL中,有很多方法可以完成字符串分割,而你选择了最慢的方法。请研究一下基于SQLCLR的分割器(你可以通过 SQL# 免费获得(我是它的创造者,但String_Split在免费版本中),或者,至少,基于XML的分割器。
@srutzky 谢谢你的评论,但是我必须在分割的数值上应用一些业务登录,所以我使用了SPLIT函数来分割数值。所以每次我都不能使用临时表。
好的,关于使用分割与临时表。但是,我也在说不要使用 那个 分割函数。基于WHILE循环的分割函数是非常低效的。有几个更好的选择。
@srutzky 你能给我提供另一种写分割函数的方法吗?
我在第一条评论中提供了一个免费的SQLCLR分割器的链接。如果你想自己写,也可以在网上搜索一些例子。
komal siddhapura
komal siddhapura
发布于 2019-11-21
0 人赞同

你可以在不使用嵌套替换函数的情况下替换所有运算符

DECLARE @Pattern VARCHAR(300) ='%[+-\*/%()]%';