String 有没有比使用太多的替换函数更好的方法来删除垃圾字符?

String 有没有比使用太多的替换函数更好的方法来删除垃圾字符?,string,tsql,replace,sql-server-2012,character,String,Tsql,Replace,Sql Server 2012,Character,我有些东西在下面 declare @t table(city varchar(100)) insert into @t values('ab,c:d\/tyu'),('frd/hj&er\gg:') select REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(city,',',' '),'"',''),':',''),'-',''),'/',''),'\',''),'&','') from @t output

我有些东西在下面

declare @t table(city varchar(100))
insert into @t values('ab,c:d\/tyu'),('frd/hj&er\gg:')

select REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(city,',',' '),'"',''),':',''),'-',''),'/',''),'\',''),'&','')
from @t

output
----------
ab cdtyu
frdhjergg
可以看出,由于垃圾字符太多,我使用了许多替换函数


有没有更好、更优雅的方法来实现这一点?

在极少数情况下,奇怪的更新是一个好主意。不要期望最好的性能,但是任何其他使用循环、递归CTE等的方法也会有它们的RBAR

这种方法的优点是:可以在表中维护replace值。您甚至可以用其他更长的字符串替换更长的字符串,这真是不可思议:通过定义顺序,您甚至可以执行级联替换

CREATE TABLE ReplaceValues (FindChar VARCHAR(1) NOT NULL
                           ,ReplWith VARCHAR(1) NOT NULL
                           ,SortOrder INT NOT NULL);
INSERT INTO ReplaceValues VALUES(',',' ',1)
                               ,('"','',2)
                               ,(':','',3)
                               ,('-','',4)
                               ,('/','',5)
                               ,('\','',6)
                               ,('&','',7);
GO
--通常不能使用古怪的内联更新,但可以将其封装在标量函数中:

CREATE FUNCTION dbo.MultiReplace(@ReplaceTarget VARCHAR(MAX))
RETURNS VARCHAR(MAX)
AS
BEGIN
    --Quirky Update: One of the rare situations where this is a good idea 
    SELECT @ReplaceTarget=REPLACE(@ReplaceTarget,rv.FindChar,rv.ReplWith)
    FROM ReplaceValues AS rv
    ORDER BY rv.SortOrder;

    RETURN @ReplaceTarget;
END
GO
--你的桌子

declare @t table(city varchar(100))
insert into @t values('ab,c:d\/tyu'),('frd/hj&er\gg:');
--…魔法就在这里:

SELECT t.city
      ,dbo.MultiReplace(t.city) AS CleanedCity
FROM @t AS t
GO
--清理

结果

city            CleanedCity
ab,c:d\/tyu     ab cdtyu
frd/hj&er\gg:   frdhjergg

一个罕见的情况下,一个古怪的更新是一个好主意。不要期望最好的性能,但是任何其他使用循环、递归CTE等的方法也会有它们的RBAR

这种方法的优点是:可以在表中维护replace值。您甚至可以用其他更长的字符串替换更长的字符串,这真是不可思议:通过定义顺序,您甚至可以执行级联替换

CREATE TABLE ReplaceValues (FindChar VARCHAR(1) NOT NULL
                           ,ReplWith VARCHAR(1) NOT NULL
                           ,SortOrder INT NOT NULL);
INSERT INTO ReplaceValues VALUES(',',' ',1)
                               ,('"','',2)
                               ,(':','',3)
                               ,('-','',4)
                               ,('/','',5)
                               ,('\','',6)
                               ,('&','',7);
GO
--通常不能使用古怪的内联更新,但可以将其封装在标量函数中:

CREATE FUNCTION dbo.MultiReplace(@ReplaceTarget VARCHAR(MAX))
RETURNS VARCHAR(MAX)
AS
BEGIN
    --Quirky Update: One of the rare situations where this is a good idea 
    SELECT @ReplaceTarget=REPLACE(@ReplaceTarget,rv.FindChar,rv.ReplWith)
    FROM ReplaceValues AS rv
    ORDER BY rv.SortOrder;

    RETURN @ReplaceTarget;
END
GO
--你的桌子

declare @t table(city varchar(100))
insert into @t values('ab,c:d\/tyu'),('frd/hj&er\gg:');
--…魔法就在这里:

SELECT t.city
      ,dbo.MultiReplace(t.city) AS CleanedCity
FROM @t AS t
GO
--清理

结果

city            CleanedCity
ab,c:d\/tyu     ab cdtyu
frd/hj&er\gg:   frdhjergg

使用函数

试试这个:

Create Function [dbo].[Removejunkcharacter]
 (@CityTempValue varchar(100))
 Returns varchar(100)
 AS
 Begin

    Declare @value as varchar(100)
    Set @value = '%[^a-z]%'
    While PatIndex(@value, @CityTempValue) > 0
        Set @CityTempValue = Stuff(@CityTempValue, PatIndex(@value, @CityTempValue), 1, '')

    Return @CityTempValue
End
Declare @t table(city varchar(100))
Insert into @t values('ab,c:d\/tyu'),('frd/hj&er\gg:')

Select t1.city AS Input,
    [dbo].[Removejunkcharacter](t1.city) AS Result
    FROM @t AS t1;
   Input            Result

ab,c:d\/tyu        abcdtyu
frd/hj&er\gg:      frdhjergg
执行查询:

Create Function [dbo].[Removejunkcharacter]
 (@CityTempValue varchar(100))
 Returns varchar(100)
 AS
 Begin

    Declare @value as varchar(100)
    Set @value = '%[^a-z]%'
    While PatIndex(@value, @CityTempValue) > 0
        Set @CityTempValue = Stuff(@CityTempValue, PatIndex(@value, @CityTempValue), 1, '')

    Return @CityTempValue
End
Declare @t table(city varchar(100))
Insert into @t values('ab,c:d\/tyu'),('frd/hj&er\gg:')

Select t1.city AS Input,
    [dbo].[Removejunkcharacter](t1.city) AS Result
    FROM @t AS t1;
   Input            Result

ab,c:d\/tyu        abcdtyu
frd/hj&er\gg:      frdhjergg
结果:

Create Function [dbo].[Removejunkcharacter]
 (@CityTempValue varchar(100))
 Returns varchar(100)
 AS
 Begin

    Declare @value as varchar(100)
    Set @value = '%[^a-z]%'
    While PatIndex(@value, @CityTempValue) > 0
        Set @CityTempValue = Stuff(@CityTempValue, PatIndex(@value, @CityTempValue), 1, '')

    Return @CityTempValue
End
Declare @t table(city varchar(100))
Insert into @t values('ab,c:d\/tyu'),('frd/hj&er\gg:')

Select t1.city AS Input,
    [dbo].[Removejunkcharacter](t1.city) AS Result
    FROM @t AS t1;
   Input            Result

ab,c:d\/tyu        abcdtyu
frd/hj&er\gg:      frdhjergg

使用函数

试试这个:

Create Function [dbo].[Removejunkcharacter]
 (@CityTempValue varchar(100))
 Returns varchar(100)
 AS
 Begin

    Declare @value as varchar(100)
    Set @value = '%[^a-z]%'
    While PatIndex(@value, @CityTempValue) > 0
        Set @CityTempValue = Stuff(@CityTempValue, PatIndex(@value, @CityTempValue), 1, '')

    Return @CityTempValue
End
Declare @t table(city varchar(100))
Insert into @t values('ab,c:d\/tyu'),('frd/hj&er\gg:')

Select t1.city AS Input,
    [dbo].[Removejunkcharacter](t1.city) AS Result
    FROM @t AS t1;
   Input            Result

ab,c:d\/tyu        abcdtyu
frd/hj&er\gg:      frdhjergg
执行查询:

Create Function [dbo].[Removejunkcharacter]
 (@CityTempValue varchar(100))
 Returns varchar(100)
 AS
 Begin

    Declare @value as varchar(100)
    Set @value = '%[^a-z]%'
    While PatIndex(@value, @CityTempValue) > 0
        Set @CityTempValue = Stuff(@CityTempValue, PatIndex(@value, @CityTempValue), 1, '')

    Return @CityTempValue
End
Declare @t table(city varchar(100))
Insert into @t values('ab,c:d\/tyu'),('frd/hj&er\gg:')

Select t1.city AS Input,
    [dbo].[Removejunkcharacter](t1.city) AS Result
    FROM @t AS t1;
   Input            Result

ab,c:d\/tyu        abcdtyu
frd/hj&er\gg:      frdhjergg
结果:

Create Function [dbo].[Removejunkcharacter]
 (@CityTempValue varchar(100))
 Returns varchar(100)
 AS
 Begin

    Declare @value as varchar(100)
    Set @value = '%[^a-z]%'
    While PatIndex(@value, @CityTempValue) > 0
        Set @CityTempValue = Stuff(@CityTempValue, PatIndex(@value, @CityTempValue), 1, '')

    Return @CityTempValue
End
Declare @t table(city varchar(100))
Insert into @t values('ab,c:d\/tyu'),('frd/hj&er\gg:')

Select t1.city AS Input,
    [dbo].[Removejunkcharacter](t1.city) AS Result
    FROM @t AS t1;
   Input            Result

ab,c:d\/tyu        abcdtyu
frd/hj&er\gg:      frdhjergg

试试这个:

declare @t table(id int, value varchar(15))

insert @t values(1, 'ab,c:d\/tyu')
insert @t values(2, 'frd/hj&er\gg')

;with t1 as
(
   select value i, id from @t
   union all
   select cast(replace(i, substring(i, PatIndex('%[^a-z0-9]%', i), 1), '') 
   as varchar(15)), id
   from t1
   where PatIndex('%[^a-z0-9]%', i) > 0
)

select t2.value as [Input], t1.i as [Result] from t1
join @t t2
on t1.id = t2.id
where PatIndex('%[^a-z0-9]%', i) = 0
option (maxrecursion 0)

试试这个:

declare @t table(id int, value varchar(15))

insert @t values(1, 'ab,c:d\/tyu')
insert @t values(2, 'frd/hj&er\gg')

;with t1 as
(
   select value i, id from @t
   union all
   select cast(replace(i, substring(i, PatIndex('%[^a-z0-9]%', i), 1), '') 
   as varchar(15)), id
   from t1
   where PatIndex('%[^a-z0-9]%', i) > 0
)

select t2.value as [Input], t1.i as [Result] from t1
join @t t2
on t1.id = t2.id
where PatIndex('%[^a-z0-9]%', i) = 0
option (maxrecursion 0)

我将此作为第二个答案,因为这是一种全新的、基于集合的方法

与我的另一个回答一样,我使用可维护的替换值表:

CREATE TABLE ReplaceValues (FindChar VARCHAR(1) NOT NULL
                           ,ReplWith VARCHAR(1) NOT NULL
                           ,SortOrder INT NOT NULL);
INSERT INTO ReplaceValues VALUES(',',' ',1)
                               ,('"','',2)
                               ,(':','',3)
                               ,('-','',4)
                               ,('/','',5)
                               ,('\','',6)
                               ,('&','',7);
GO

declare @t table(city varchar(100))
insert into @t values('ab,c:d\/tyu'),('frd/hj&er\gg:');
--查询将使用一个计数表动态生成一个运行的数字。然后使用
子字符串
拾取每个字符和任何单个字符,并在替换值的表中找到它。如果未找到任何内容,则使用该值,否则使用替换值。最后,使用XML的
重新连接分离的字符

WITH Tally AS(SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nmbr FROM master..spt_values) --approx 2500 values. Need more? Use CROSS JOIN

SELECT t.city 
,(
    SELECT ISNULL(rv.ReplWith,SUBSTRING(t2.city,Nmbr,1))
    FROM @t AS t2
    CROSS APPLY(SELECT TOP (LEN(t2.City)) Nmbr FROM Tally) AS A
    LEFT JOIN ReplaceValues AS rv ON rv.FindChar=SUBSTRING(t2.city,Nmbr,1)
    WHERE t.city=t2.city
    ORDER BY A.Nmbr
    FOR XML PATH(''),TYPE
).value(N'.','nvarchar(max)') ReBuilt
FROM @t AS t
GO
--Clean-Up

DROP TABLE ReplaceValues;

我将此作为第二个答案,因为这是一种全新的、基于集合的方法

与我的另一个回答一样,我使用可维护的替换值表:

CREATE TABLE ReplaceValues (FindChar VARCHAR(1) NOT NULL
                           ,ReplWith VARCHAR(1) NOT NULL
                           ,SortOrder INT NOT NULL);
INSERT INTO ReplaceValues VALUES(',',' ',1)
                               ,('"','',2)
                               ,(':','',3)
                               ,('-','',4)
                               ,('/','',5)
                               ,('\','',6)
                               ,('&','',7);
GO

declare @t table(city varchar(100))
insert into @t values('ab,c:d\/tyu'),('frd/hj&er\gg:');
--查询将使用一个计数表动态生成一个运行的数字。然后使用
子字符串
拾取每个字符和任何单个字符,并在替换值的表中找到它。如果未找到任何内容,则使用该值,否则使用替换值。最后,使用XML的
重新连接分离的字符

WITH Tally AS(SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nmbr FROM master..spt_values) --approx 2500 values. Need more? Use CROSS JOIN

SELECT t.city 
,(
    SELECT ISNULL(rv.ReplWith,SUBSTRING(t2.city,Nmbr,1))
    FROM @t AS t2
    CROSS APPLY(SELECT TOP (LEN(t2.City)) Nmbr FROM Tally) AS A
    LEFT JOIN ReplaceValues AS rv ON rv.FindChar=SUBSTRING(t2.city,Nmbr,1)
    WHERE t.city=t2.city
    ORDER BY A.Nmbr
    FOR XML PATH(''),TYPE
).value(N'.','nvarchar(max)') ReBuilt
FROM @t AS t
GO
--Clean-Up

DROP TABLE ReplaceValues;

下面是另一个基于Shnugo的
ReplaceValues
表和递归cte的相当简单的解决方案:

Shnugo的桌子:

CREATE TABLE ReplaceValues (FindChar VARCHAR(1) NOT NULL
                           ,ReplWith VARCHAR(1) NOT NULL
                           ,SortOrder INT NOT NULL);
INSERT INTO ReplaceValues VALUES(',',' ',1)
                               ,('"','',2)
                               ,(':','',3)
                               ,('-','',4)
                               ,('/','',5)
                               ,('\','',6)
                               ,('&','',7);
GO
样本数据:

declare @t table(city varchar(100))
insert into @t values('ab,c:d\/tyu'),('frd/hj&er\gg:')
查询:

;WITH CTE AS
(
    SELECT city, 1 as level
    FROM @T 
    UNION ALL
    SELECT CAST(Replace(city,FindChar,ReplWith) as varchar(100)), level + 1
    FROM CTE 
    INNER JOIN ReplaceValues ON level = SortOrder
)

select TOP 1 WITH TIES City
from CTE
ORDER BY level DESC
结果:

City
1   frdhjergg
2   ab cdtyu

下面是另一个基于Shnugo的
ReplaceValues
表和递归cte的相当简单的解决方案:

Shnugo的桌子:

CREATE TABLE ReplaceValues (FindChar VARCHAR(1) NOT NULL
                           ,ReplWith VARCHAR(1) NOT NULL
                           ,SortOrder INT NOT NULL);
INSERT INTO ReplaceValues VALUES(',',' ',1)
                               ,('"','',2)
                               ,(':','',3)
                               ,('-','',4)
                               ,('/','',5)
                               ,('\','',6)
                               ,('&','',7);
GO
样本数据:

declare @t table(city varchar(100))
insert into @t values('ab,c:d\/tyu'),('frd/hj&er\gg:')
查询:

;WITH CTE AS
(
    SELECT city, 1 as level
    FROM @T 
    UNION ALL
    SELECT CAST(Replace(city,FindChar,ReplWith) as varchar(100)), level + 1
    FROM CTE 
    INNER JOIN ReplaceValues ON level = SortOrder
)

select TOP 1 WITH TIES City
from CTE
ORDER BY level DESC
结果:

City
1   frdhjergg
2   ab cdtyu

由于我使用的是sql server 2014,我只剩下替换和不翻译(sql server 2017)…请注意,因为我使用的是sql server 2014,我剩下的是替换和不翻译(sql server 2017)…请注意。这种方法有一个问题(也使用了古怪的更新),即一些值不仅仅是要删除的。。。至少逗号被翻译成了空白…@Vinoth,我只是想避免函数…这可以用基于集合的方式来完成吗?这种方法的一个问题(也使用了奇怪的更新)是,事实上,有些值不只是要删除。。。至少逗号被翻译成了空白…@Vinoth,我只是想避免函数…这可以用基于集合的方式完成吗?@priyanka.sarkar请看我的第二个答案。。。什么更重要?可读性还是原则?顺便说一句:奇怪的更新在性能上非常好。…@priyanka.sarkar请看我的第二个答案。。。什么更重要?可读性还是原则?顺便说一句:古怪的更新在性能上相当好。。。