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);
    }
}