Aggregate replace in SQL Server?

前端 未结 3 1888
名媛妹妹
名媛妹妹 2021-01-22 03:25

What I\'m trying to achieve is to make dynamic a series of replacements that have to be performed on a certain field. (To make things even easier, I want in fact to remove data,

相关标签:
3条回答
  • 2021-01-22 03:43

    Once you implement the CLR aggregate function below, you can do:

    SELECT dbo.ReplaceAgg(t.[text], w.badword, w.goodword) // call CLR aggregate function
    FROM [Texts] t CROSS JOIN BadWords w
    GROUP BY t.[text]
    

    CLR aggregate function in C#

    /// <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);
        }
    }
    
    0 讨论(0)
  • 2021-01-22 03:44

    You might have to write a scalar function to which you pass the original string, and enough information for it to know which strings to remove, and have it loop through them and return the result of the set of replacements.

    0 讨论(0)
  • 2021-01-22 03:53

    You can setup a table variable with FromValue and ToValue and use a while loop to do the replacements.

    -- 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
    

    Result:

    Value 
    -------------------
    first fourth fifth
    first fourth fifth
    

    If you only want to query the values you can do something like this.

    ;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
    
    0 讨论(0)
提交回复
热议问题