【问题标题】:Replace multiple characters from string without using any nested replace functions在不使用任何嵌套替换函数的情况下替换字符串中的多个字符
【发布时间】:2013-11-19 01:09:27
【问题描述】:

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

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

运算符或模式: (+, -, *, /, %, (, ))

替换字符: ~

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

我曾尝试使用 嵌套替换 函数进行以下查询,并且得到了所需的输出:

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

如何在不使用嵌套替换函数的情况下替换所有运算符?

【问题讨论】:

  • 为什么多个 Replce 函数有问题?
  • 我还有其他一些运算符,我必须多次编写替换函数。所以我正在寻找替代方法来做到这一点。

标签: sql sql-server sql-server-2008 tsql replace


【解决方案1】:

我相信如果您使用表格来驱动它,它会更容易且更具可读性。

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'...等,它正在替换所有出现的@ 987654324@ 在每行的字段中带有+a,但不是bc 等替换(?)
  • @CodeJockey 创建一个新问题,引用此答案,并显示您当前的代码是什么以及您尝试操作的数据。然后在此处发布该问题的链接,我会回答。
  • @SolomonRutzky 嘿!我正在尝试完全按照 CodeJockey 的要求去做。你介意看看这个问题吗? stackoverflow.com/questions/45800289
【解决方案2】:

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

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

【讨论】:

  • 我想替代做这个操作。
【解决方案3】:

最简单的方法是使用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 Demo

【讨论】:

    【解决方案4】:

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

    分割函数

    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
    

    程序中使用的代码:

    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
    

    输出

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

    【讨论】:

    • 这不需要拆分功能。它服务的唯一目的是动态吐出一张桌子。由于替换字符是一个小的有限集,因此创建一个临时表要好得多,如@Shane 的答案所示。此外,在 T-SQL 中完成字符串拆分的方法有很多,而您选择了最慢的。请查看基于 SQLCLR 的拆分器(您可以通过 SQL# 免费获得(我是它的创建者,但 String_Split 在免费版本中),或者至少是基于 XML 的拆分器。
    • @srutzky 感谢您的评论,但我必须对拆分值应用一些业务登录,因此我使用 SPLIT 函数拆分值。所以每次我都不能使用临时表。
    • 好的,关于使用拆分与临时表。但是,我也说不要使用 that 拆分功能。基于 WHILE 循环的拆分函数效率极低。有几个更好的选择。
    • @srutzky 能否提供另一种编写拆分函数的方法
    • 我在第一条评论中提供了一个指向免费 SQLCLR 拆分器的链接。或者,如果您想编写自己的示例,可以在网上搜索示例。
    【解决方案5】:

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

    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 
    

    【讨论】:

      猜你喜欢
      • 2015-02-12
      • 2015-07-18
      • 2014-12-24
      • 1970-01-01
      • 2020-08-31
      • 1970-01-01
      • 2016-01-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多