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请看我的第二个答案。。。什么更重要?可读性还是原则?顺便说一句:古怪的更新在性能上相当好。。。