SQL Server non supporta la sostituzione di schemi di più caratteri, quindi per farlo REPLACEsarebbe necessario eseguire 10 operazioni.
Con questo in mente un modo per farlo sarebbe un CTE ricorsivo per elaborare le cifre da 0 a 9 in sequenza.
Esegue la sostituzione e quindi controlla la lunghezza delle stringhe prima e dopo per sapere quanti caratteri di quel numero c'erano e cosa bisogna aggiungere al totale.
DECLARE @Input VARCHAR(8000) = 'GR35hc7vdH35';
WITH R(Level,Input,Accumulator,StringLength)
AS (SELECT 0,
Input,
0,
DATALENGTH(Input)
FROM (SELECT REPLACE(@Input, '0', '')) D(Input)
UNION ALL
SELECT NewLevel,
NewInput,
Accumulator + NewLevel * ( StringLength - NewStringLength ),
NewStringLength
FROM R
CROSS APPLY (SELECT Level + 1) C(NewLevel)
CROSS APPLY (SELECT REPLACE(Input, NewLevel, '')) C2(NewInput)
CROSS APPLY (SELECT DATALENGTH(NewInput)) C3(NewStringLength)
WHERE NewLevel <= 9)
SELECT Input AS Col1,
Accumulator AS Col2
FROM R
WHERE Level = 9;
Oppure puoi usare CLR ed espressioni regolari (versione compatibile di SQL Server 2012).
using System;
using System.Data.SqlTypes;
using System.Collections;
using System.Text.RegularExpressions;
public partial class UserDefinedFunctions
{
private static readonly Regex digitRegex = new Regex(@"[\d]", RegexOptions.Compiled);
[Microsoft.SqlServer.Server.SqlFunction(FillRowMethodName = "FillRow",
TableDefinition = @"Stripped NVARCHAR(MAX),
Total INT")]
public static IEnumerable ReplaceAndTotalise(SqlString input)
{
if (!input.IsNull)
{
int total = 0;
string stripped = digitRegex.Replace((string)input, match =>
{
total += int.Parse(match.Value);
return string.Empty;
});
yield return new Tuple<string, int>(stripped, total);
}
}
public static void FillRow(object resultObject, out SqlString stripped, out SqlInt32 total)
{
var result = (Tuple<string, int>)resultObject;
stripped = result.Item1;
total = result.Item2;
}
}
Esempio di utilizzo
SELECT Stripped,
Total
FROM [dbo].[ReplaceAndTotalise]('GR35hc7vdH35')