如何在SQL中替换多个字符?

kie*_*iev 34 sql sql-server sql-server-2005 sql-function

这是基于类似的问题如何替换Access SQL中的多个字符?

我写了这个,因为sql server 2005似乎对where子句中的19个替换的replace()函数有限制.

我有以下任务:需要在列上执行匹配,并使用replace()函数提高匹配剥离多个不需要的字符的机会

DECLARE @es NVarChar(1) SET @es = ''
DECLARE @p0 NVarChar(1) SET @p0 = '!'
DECLARE @p1 NVarChar(1) SET @p1 = '@'
---etc...

SELECT *
FROM t1,t2 
WHERE  REPLACE(REPLACE(t1.stringkey,@p0, @es), @p1, @es) 
     = REPLACE(REPLACE(t2.stringkey,@p0, @es), @p1, @es)    
---etc 
Run Code Online (Sandbox Code Playgroud)

如果where子句中有> 19 REPLACE(),则它不起作用.所以我想出的解决方案是在这个例子中创建一个名为trimChars的sql函数(请原谅他们从@ 22开始

CREATE FUNCTION [trimChars] (
   @string varchar(max)
) 

RETURNS varchar(max) 
AS
BEGIN

DECLARE @es NVarChar(1) SET @es = ''
DECLARE @p22 NVarChar(1) SET @p22 = '^'
DECLARE @p23 NVarChar(1) SET @p23 = '&'
DECLARE @p24 NVarChar(1) SET @p24 = '*'
DECLARE @p25 NVarChar(1) SET @p25 = '('
DECLARE @p26 NVarChar(1) SET @p26 = '_'
DECLARE @p27 NVarChar(1) SET @p27 = ')'
DECLARE @p28 NVarChar(1) SET @p28 = '`'
DECLARE @p29 NVarChar(1) SET @p29 = '~'
DECLARE @p30 NVarChar(1) SET @p30 = '{'

DECLARE @p31 NVarChar(1) SET @p31 = '}'
DECLARE @p32 NVarChar(1) SET @p32 = ' '
DECLARE @p33 NVarChar(1) SET @p33 = '['
DECLARE @p34 NVarChar(1) SET @p34 = '?'
DECLARE @p35 NVarChar(1) SET @p35 = ']'
DECLARE @p36 NVarChar(1) SET @p36 = '\'
DECLARE @p37 NVarChar(1) SET @p37 = '|'
DECLARE @p38 NVarChar(1) SET @p38 = '<'
DECLARE @p39 NVarChar(1) SET @p39 = '>'
DECLARE @p40 NVarChar(1) SET @p40 = '@'
DECLARE @p41 NVarChar(1) SET @p41 = '-'

return   REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
       @string, @p22, @es), @p23, @es), @p24, @es), @p25, @es), @p26, @es), @p27, @es), @p28, @es), @p29, @es), @p30, @es), @p31, @es), @p32, @es), @p33, @es), @p34, @es), @p35, @es), @p36, @es), @p37, @es), @p38, @es), @p39, @es), @p40, @es), @p41, @es)
END 
Run Code Online (Sandbox Code Playgroud)

然后,除了其他替换字符串之外,还可以使用它

SELECT *
FROM t1,t2 
WHERE  trimChars(REPLACE(REPLACE(t1.stringkey,@p0, @es), @p1, @es) 
         = REPLACE(REPLACE(t2.stringkey,@p0, @es), @p1, @es))   
Run Code Online (Sandbox Code Playgroud)

我创建了一些更多的函数来做类似的替换,就像trimChars(trimMoreChars(

SELECT *
FROM t1,t2 
WHERE  trimChars(trimMoreChars(REPLACE(REPLACE(t1.stringkey,@p0, @es), @p1, @es) 
         = REPLACE(REPLACE(t2.stringkey,@p0, @es), @p1, @es)))
Run Code Online (Sandbox Code Playgroud)

在性能和可能更清晰的实现方面,有人能给我一个更好的解决方案吗?

Jul*_*iet 49

SQL中一个有用的技巧是@var = function(...)用于分配值的能力.如果您的记录集中有多个记录,则var会多次分配副作用:

declare @badStrings table (item varchar(50))

INSERT INTO @badStrings(item)
SELECT '>' UNION ALL
SELECT '<' UNION ALL
SELECT '(' UNION ALL
SELECT ')' UNION ALL
SELECT '!' UNION ALL
SELECT '?' UNION ALL
SELECT '@'

declare @testString varchar(100), @newString varchar(100)

set @teststring = 'Juliet ro><0zs my s0x()rz!!?!one!@!@!@!'
set @newString = @testString

SELECT @newString = Replace(@newString, item, '') FROM @badStrings

select @newString -- returns 'Juliet ro0zs my s0xrzone'
Run Code Online (Sandbox Code Playgroud)

  • @kiev:创建用户定义的函数是正确的方法.但是,你最好使用我的方法,而不是将bajillion替换为彼此,因为我的方法支持无限次的替换.您可以通过传入逗号分隔的字符串列表来使函数更加动态,使用拆分函数(http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=50648)将列表转换为一个表,然后返回替换的字符串. (2认同)

Cad*_*oux 23

我会认真考虑改为使用CLR UDF 并使用正则表达式(字符串和模式都可以作为参数传入)来进行完整的搜索并替换一系列字符.它应该轻松胜过这个SQL UDF.


Dua*_*nne 20

我真的很喜欢@ Juliett的解决方案!我只想使用CTE来获取所有无效字符:

DECLARE @badStrings VARCHAR(100)
DECLARE @teststring VARCHAR(100)

SET @badStrings = '><()!?@'
SET @teststring = 'Juliet ro><0zs my s0x()rz!!?!one!@!@!@!'

;WITH CTE AS
(
  SELECT SUBSTRING(@badStrings, 1, 1) AS [String], 1 AS [Start], 1 AS [Counter]
  UNION ALL
  SELECT SUBSTRING(@badStrings, [Start] + 1, 1) AS [String], [Start] + 1, [Counter] + 1 
  FROM CTE 
  WHERE [Counter] < LEN(@badStrings)
)

SELECT @teststring = REPLACE(@teststring, CTE.[String], '') FROM CTE

SELECT @teststring
Run Code Online (Sandbox Code Playgroud)

Juliet ro0zs我的s0xrzone


Gui*_*rez 5

我建议您创建一个标量用户定义函数。这是一个例子(提前抱歉,因为变量名是西班牙语):

CREATE FUNCTION [dbo].[Udf_ReplaceChars] (
  @cadena VARCHAR(500),  -- String to manipulate
  @caracteresElim VARCHAR(100),  -- String of characters to be replaced
  @caracteresReem VARCHAR(100)   -- String of characters for replacement
) 
RETURNS VARCHAR(500)
AS
BEGIN
  DECLARE @cadenaFinal VARCHAR(500), @longCad INT, @pos INT, @caracter CHAR(1), @posCarER INT;
  SELECT
    @cadenaFinal = '',
    @longCad = LEN(@cadena),
    @pos = 1;

  IF LEN(@caracteresElim)<>LEN(@caracteresReem)
    BEGIN
      RETURN NULL;
    END

  WHILE @pos <= @longCad
    BEGIN
      SELECT
        @caracter = SUBSTRING(@cadena,@pos,1),
        @pos = @pos + 1,
        @posCarER = CHARINDEX(@caracter,@caracteresElim);

      IF @posCarER <= 0
        BEGIN
          SET @cadenaFinal = @cadenaFinal + @caracter;
        END
      ELSE
        BEGIN
          SET @cadenaFinal = @cadenaFinal + SUBSTRING(@caracteresReem,@posCarER,1)
        END
    END

  RETURN @cadenaFinal;
END
Run Code Online (Sandbox Code Playgroud)

下面是一个使用这个函数的例子:

SELECT dbo.Udf_ReplaceChars('This is a test.','sat','Z47');
Run Code Online (Sandbox Code Playgroud)

结果是:7hiZ iZ 4 7eZ7。

如您所见,@caracteresElim参数的每个字符都被替换为与参数相同位置的字符@caracteresReem