SQL - 替换字符串中的所有“ASCII /特殊字符”

时间:2014-03-06 23:33:43

标签: sql tsql replace cursor special-characters

编辑:我的应用程序中有大约80个字符导致问题,因此我不想为每个字符硬编码REPLACE。我认为用两列“特殊字符”和“替换字符”创建一个单独的表会更容易,我将从包含“StringTest”列的原始表中删除这些列。我的目标是找出如何使用字符表替换字符串表中的字符。

我试图用SQL Server中的“MappedCharacters”(A,AE,C)替换所有“特殊字符”(即À,Æ,Ç)。我尝试了两种不同的技术,一种使用光标,一种没有光标,搜索字符串并用映射的字符替换所有特殊字符。我的每个方法只替换它们与字符串在同一行中的字符。 以前的例子:

num   SpecialCharacter    MappedCharacter    StringTest
 1           À                   A             StringÀÆ
 2           Æ                   AE            ÆStringÆ
 3           Ç                   C             StrÇÀing

之后的例子:

num   SpecialCharacter    MappedCharacter    StringTest
 1           À                   A             StringAÆ
 2           Æ                   AE            AEStringAE
 3           Ç                   C             StrCÀing

首选输出:

num   SpecialCharacter    MappedCharacter    StringTest
 1           À                   A             StringAAE
 2           Æ                   AE            AEStringAE
 3           Ç                   C             StrCAing

因此,您可以看到我想要替换StringTest中的所有“特殊字符”,但只有同一行中的字符才会被替换。

我还没有想出如何做到这一点。

以下是我一直试图修改的两个SQL代码(我只需要一个工作)

第一种方法:

              DECLARE @cASCIINum INT;
              DECLARE @cSpecialChar VARCHAR(50);
              DECLARE @cMappedChar VARCHAR(50);
              DECLARE @cStringTest VARCHAR(50);

              DECLARE @mapCursor as CURSOR;

              SET @mapCursor = CURSOR FOR
              SELECT [ASCIINum]
                    ,[SpecialChar]
                    ,[MappedChar]
                    ,[StringTest]
              FROM [intranet].[dbo].[CharMapTestTab]; 

              OPEN @mapCursor;
              FETCH NEXT FROM @mapCursor INTO @cASCIINum,
                                              @cSpecialChar,
                                              @cMappedChar,
                                              @cStringTest;

                WHILE @@FETCH_STATUS = 0
                BEGIN

                  UPDATE [intranet].[dbo].[CharMapTestTab]
                  SET StringTest = REPLACE(StringTest, SpecialChar, MappedChar)
                  WHERE SpecialChar <> MappedChar

                END

                CLOSE @mapCursor;
                DEALLOCATE @mapCursor;

第二种方法:

            DECLARE @ASCIINum INT = 0

            WHILE (1 = 1) 
            BEGIN  

              SELECT @ASCIINum = ASCIINum
              FROM [intranet].[dbo].[CharMapTestTab]
              WHERE ASCIINum > @ASCIINum 
              ORDER BY ASCIINum

              IF @@ROWCOUNT = 0 BREAK;

                  UPDATE [intranet].[dbo].[CharMapTestTab]
                  SET StringTest = REPLACE(StringTest, SpecialChar, MappedChar)
                  WHERE SpecialChar <> MappedChar


              SELECT TOP 1000 [ASCIINum]
                  ,[SpecialChar]
                  ,[MappedChar]
                  ,[StringTest]
              FROM [intranet].[dbo].[CharMapTestTab]



            END

5 个答案:

答案 0 :(得分:5)

试试这个,它比循环更好,因为只有1个更新:

-- create test table vc
create table vc(StringTest varchar(20))
insert vc values('StringÀÆ'), ('ÆStringÆ')
go

-- create test table CharacterMapping
create table CharacterMapping(SpecialCharacter char(1), MappedCharacter varchar(2))
insert CharacterMapping values('À', 'A'),('Æ', 'AE'), ('Ç', 'C')
go

--build the varchar for updating
declare @x varchar(max) = 'StringTest'
select @x = 'replace('+@x+', ''' + SpecialCharacter + ''','''+MappedCharacter+''')'  
from CharacterMapping
set @x = 'update vc set StringTest=' + @x +' from vc'

exec (@x)

select * from vc

结果:

StringAAE
AEStringAE

答案 1 :(得分:1)

我会创建一个单独的映射表,其中包含坏字符及其对应的好字符,每行一组。然后遍历该表并为每个字符集执行替换。

DECLARE @map TABLE (
    id INT,
    badChar CHAR,
    goodChar CHAR
)

DECLARE @strings TABLE (
    searchString VARCHAR(50)
)

INSERT INTO @map 
VALUES 
(1, 'y', 'a'),
(2, 'z', 'b')

DECLARE @curRow INT, @totalRows INT
SET @curRow = 1
SELECT @totalRows = COUNT(*) FROM @map

INSERT INTO @strings
VALUES
('zcccyccz'),
('cccyccz')

WHILE @curRow <= @totalRows
BEGIN
    UPDATE @strings 
    SET searchString = REPLACE(searchString, badChar, goodChar) 
    FROM @map 
    WHERE id = @curRow

    SET @curRow = @curRow + 1
END

SELECT * FROM @strings

--Output
--bcccaccb
--cccaccb

答案 2 :(得分:0)

update table  
set column = REPLACE(column,'À','A') 
where column like ('%À%') 
update table  
set column = REPLACE(column,'Æ','AE') 
where column like ('%Æ%') 

我会把第3个留给你

或者这可能更有效

update table  
set column = REPLACE(REPLACE(column,'À','A'),'Æ','AE')
where column like ('%À%') 
   or column like ('%Æ%')

如果你真的想处理一个映射字符列表,那么这不是一个正确的答案

答案 3 :(得分:0)

知道表中有多少行以及估计有多少行具有“特殊字符”会很有帮助。还有,只有3个特殊字符吗?如果你有40个或更少的特殊字符,它可能看起来很荒谬,但我只是嵌套尽可能多的REPLACE()调用,因为你有特殊字符,如:

UPDATE YourTable SET YourColumn = REPLACE(
                                  REPLACE(
                                  REPLACE(YourColumn,'Ç','C')
                                  ,'Æ','AE')
                              ,'À','A')

如果大多数行都有特殊字符,我会跳过任何WHERE。如果只有几行有特殊字符,我会使用CTE来识别它们:

;WITH AllSpecialRows AS
(
SELECT PrimaryKey FROM YourTable WHERE YourColumn LIKE '%À%'
UNION 
SELECT PrimaryKey FROM YourTable WHERE YourColumn LIKE '%Æ%'
UNION 
SELECT PrimaryKey FROM YourTable WHERE YourColumn LIKE '%Ç%'
)
UPDATE y
    SET YourColumn = REPLACE(
                     REPLACE(
                     REPLACE(YourColumn,'Ç','C')
                     ,'Æ','AE')
                     ,'À','A')
    FROM YourTable                  y
        INNER JOIN AllSpecialRows   s ON y.PrimaryKey =s.PrimaryKey

答案 4 :(得分:0)

@ t-clausen.dk回答Table变量和临时表,只是为了避免人们用其他表来搞乱他们的dev数据库。

表变量:

-- Create test table variable @CharacterMapping
DECLARE @CharacterMapping TABLE (SpecialCharacter char(1), MappedCharacter varchar(2))
INSERT @CharacterMapping VALUES('À', 'A'), ('Æ', 'AE'), ('Ç', 'C')

--Build the varchar for updating
DECLARE @x varchar(max) = 'StringTest'
SELECT @x = 'replace('+@x+', ''' + SpecialCharacter + ''',''' + MappedCharacter + ''')'  
FROM @CharacterMapping
SET @x = 'DECLARE @vc TABLE(StringTest varchar(20));'
        + ' insert @vc values(''StringÀÆ''), (''ÆStringÆ'');'
        + 'update @vc set StringTest=' + @x +' from @vc;' 
        + 'SELECT * FROM @vc;'

Exec (@x)
GO

使用Temp表:

-- Create test temp table #vc
CREATE TABLE #vc(StringTest varchar(20))
INSERT #vc VALUES('StringÀÆ'), ('ÆStringÆ')

-- Create test table CharacterMapping
DECLARE @CharacterMapping TABLE (SpecialCharacter char(1), MappedCharacter varchar(2))
INSERT @CharacterMapping VALUES('À', 'A'), ('Æ', 'AE'), ('Ç', 'C')

--Build the varchar for updating
DECLARE @x varchar(max) = 'StringTest'
SELECT @x = 'replace('+@x+', ''' + SpecialCharacter + ''',''' + MappedCharacter + ''')'  
FROM @CharacterMapping
SET @x = 'update #vc set StringTest=' + @x +' from #vc'

-- Execute
EXEC (@x)

-- Select the results 
SELECT * FROM #vc;

-- Drop temp table
DROP TABLE #vc;

GO