正如 cmets 中提到的 - 这应该在表示层中完成,而不是在 SQL 中。
不过,这并不妨碍它变得有趣!
关键是使用区分大小写的排序规则。在此示例中,我选择了 SQL_Latin1_General_CP1_CS_AS(“CS”=CaseSensitive。“CI”=CaseInsensitive)
虽然解决方案涉及循环(在这种情况下为递归 CTE),但您永远不会在这种事情上获得良好的性能
DECLARE @t table (
a char(10)
);
INSERT INTO @t (a)
VALUES ('AbC')
, ('ABCDEFGHIJ')
, ('aBCdEFghij')
, ('AbcdefhhiJ')
, ('ABcdEFGhij')
;
--SELECT a
-- , a COLLATE SQL_Latin1_General_CP1_CS_AS As case_sensitive_collation
-- , Replace(a COLLATE SQL_Latin1_General_CP1_CS_AS, 'A', '#') As case_sensitive_replace
--FROM @t
--;
; WITH characters_to_replace AS (
SELECT number
, Char(number) As c
, Row_Number() OVER (ORDER BY number) As sequence
FROM dbo.numbers
WHERE number BETWEEN 1 AND 255 -- basic characters
AND number NOT BETWEEN 65 AND 90 -- Exclude capital A-Z
)
, replacements AS (
SELECT a As original_value
, Cast(a COLLATE SQL_Latin1_General_CP1_CS_AS As nvarchar(max)) As new_value
, Cast(0 As bigint) As sequence
FROM @t
UNION ALL
SELECT replacements.original_value
, Cast(Replace(replacements.new_value, characters_to_replace.c, '') As nvarchar(max))
, characters_to_replace.sequence
FROM replacements
INNER
JOIN characters_to_replace
ON characters_to_replace.sequence = replacements.sequence + 1
)
SELECT original_value
, new_value
FROM replacements
WHERE sequence = (SELECT Max(sequence) FROM characters_to_replace)
OPTION (MaxRecursion 255)
;