的样本数据:
declare @RandomString table (ID int not null,ItemValue varchar(500) not null)
insert into @RandomString(ID,ItemValue) values
(1,'*Test"'),
(2,'?Test*')
declare @SearchCharReplacement table (Original varchar(500) not null,Replacement varchar(500) not null)
insert into @SearchCharReplacement(Original,Replacement) values
('*','`star`'),
('?','`quest`'),
('"','`quot`'),
(';','`semi`')
而且UPDATE
:
;With Replacements as (
select
ID,ItemValue,0 as RepCount
from
@RandomString
union all
select
ID,SUBSTRING(REPLACE(ItemValue,Original,Replacement),1,500),rs.RepCount+1
from
Replacements rs
inner join
@SearchCharReplacement scr
on
CHARINDEX(scr.Original,rs.ItemValue) > 0
), FinalReplacements as (
select
ID,ItemValue,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY RepCount desc) as rn
from
Replacements
)
update rs
set ItemValue = fr.ItemValue
from
@RandomString rs
inner join
FinalReplacements fr
on
rs.ID = fr.ID and
rn = 1
主要生产:
select * from @RandomString
ID ItemValue
----------- -----------------------
1 `star`Test`quot`
2 `quest`Test`star`
这样做是它与不变的文本开始(顶部选择Replacements
),那么它会尝试应用任何有效的替换(第二个选择i n Replacements
)。它将做的是继续应用这第二个选择,根据它产生的结果,直到没有新的行产生。这被称为递归公用表表达式(CTE)。
然后,我们使用第二个CTE(这次是一个非递归函数)FinalReplacements
对第一个CTE产生的所有行进行编号,为最后产生的行分配较低的行号。从逻辑上讲,这些是应用上次适用转换的结果,因此不再包含任何要替换的原始字符。因此,我们可以使用行号1对原始表执行更新。
该查询确实做了比绝对必要的更多的工作 - 对于少量的替换字符行,它不太可能太低效。我们可以通过定义单一订单来清除它,以便应用替代品。
其实,所有的更新换代确实是会发生 - 所有4个可能的结果计算,并行。然后SQL Server随意将其中一个作为“更新”应用。 –
此外,我已经将您的示例表标记为试图让它们更易于阅读的代码 - 但我有点不确定哪些字符是示例数据的一部分,vs您可能添加了尝试格式化它们。 –