SQL Server中的聚合替换?
我试图实现的是在某个领域进行一系列的动态替换。为了让事情变得更简单,我实际上想要删除数据,所以我将始终与 说有时候我只需要做一次替换:SQL Server中的聚合替换?,sql,tsql,dynamic,replace,Sql,Tsql,Dynamic,Replace,我试图实现的是在某个领域进行一系列的动态替换。为了让事情变得更简单,我实际上想要删除数据,所以我将始终与 说有时候我只需要做一次替换: ... REPLACE(myField, stringToRemove, '') 有时,我需要两个替代品: ... REPLACE(REPLACE(myField, stringToRemove, ''), anotherStringToRemove, '') 然而,我需要使其动态化,我不知道我将拥有多少这些值,因此,我必须进行多少替换和删除 我尝试搜索聚合
... REPLACE(myField, stringToRemove, '')
有时,我需要两个替代品:
... REPLACE(REPLACE(myField, stringToRemove, ''), anotherStringToRemove, '')
然而,我需要使其动态化,我不知道我将拥有多少这些值,因此,我必须进行多少替换和删除
我尝试搜索聚合字符串操作函数,当然,没有。我也知道这可以通过CLR聚合函数实现,但我不可能使用它
有什么想法吗?您可能需要编写一个标量函数,将原始字符串传递给它,并提供足够的信息让它知道要删除哪些字符串,然后让它循环遍历它们并返回替换集的结果。您可以使用FromValue和ToValue设置一个表变量,并使用while循环进行替换
-- Table to replace in
declare @T table
(
Value varchar(50)
)
insert into @T values
('first second third'),
('first second third')
-- Table with strings to replace
declare @Rep table
(
ID int identity primary key,
FromValue varchar(50),
ToValue varchar(50)
)
insert into @Rep values
('second', 'fourth'),
('third', 'fifth')
declare @ID int
select @ID = max(ID)
from @Rep
while @ID > 0
begin
update @T
set Value = replace(Value, FromValue, ToValue)
from @Rep
where ID = @ID
set @ID -= 1
end
select *
from @T
结果:
Value
-------------------
first fourth fifth
first fourth fifth
如果您只想查询这些值,可以执行以下操作
;with C as
(
select 0 as ID,
Value,
0 as Lvl
from @T
union all
select R.ID,
cast(replace(C.Value, R.FromValue, R.ToValue) as varchar(50)),
Lvl + 1
from @Rep as R
inner join C
on C.ID + 1 = R.ID
)
select top 1 with ties Value
from C
order by Lvl desc
实现以下CLR聚合函数后,您可以执行以下操作:
SELECT dbo.ReplaceAgg(t.[text], w.badword, w.goodword) // call CLR aggregate function
FROM [Texts] t CROSS JOIN BadWords w
GROUP BY t.[text]
C语言中的CLR聚合函数
替换调用量的条件是什么?动态变量。现在,它是与特定条件匹配的行数。您可以将其想象为一个配置表:replacementstringtoremove nvarcharI bow!你不仅一针见血,而且让它看起来简单,这通常是一个好老师的标志。非常感谢@阿尔法-谢谢,我很高兴能帮上忙。
/// <summary>
/// Allows to apply regex-replace operations to the same string.
/// For example:
/// SELECT dbo.ReplaceAgg(t.[text], w.badpattern, "...")
/// FROM [Texts] t CROSS JOIN BadPatterns w
/// GROUP BY t.[text]
/// </summary>
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.UserDefined,
IsInvariantToDuplicates = true, IsInvariantToOrder = false,
IsInvariantToNulls = true, MaxByteSize = -1)]
public class RegexReplaceAgg : IBinarySerialize
{
private string str;
private string needle;
private string replacement;
public void Init()
{
str = null;
needle = null;
replacement = null;
}
public void Accumulate(SqlString haystack, SqlString needle, SqlString replacement)
{
// Null values are excluded from aggregate.
if (needle.IsNull) return;
if (replacement.IsNull) return;
if (haystack.IsNull) return;
str = str ?? haystack.Value;
this.needle = needle.Value;
this.replacement = replacement.Value;
str = Regex.Replace(str, this.needle, this.replacement, RegexOptions.Compiled | RegexOptions.CultureInvariant);
}
public void Merge(RegexReplaceAgg group)
{
Accumulate(group.Terminate(), new SqlString(needle), new SqlString(replacement));
}
public SqlString Terminate() => new SqlString(str);
public void Read(BinaryReader r)
{
str = r.ReadString();
needle = r.ReadString();
replacement = r.ReadString();
}
public void Write(BinaryWriter w)
{
w.Write(str);
w.Write(needle);
w.Write(replacement);
}
}