I am using the ITVF function (table function). In terms of performance, the built-in function works like a view
CREATE FUNCTION [dbo].[udf_Split_Capitals_In_Str] (@str VARCHAR(8000)) RETURNS TABLE AS RETURN WITH Tally (n) AS ( SELECT TOP (LEN (@str)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0)) a(n) CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n) CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n) CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d(n) ) SELECT New_Str = STUFF(( SELECT CASE WHEN SUBSTRING(@str, n,1) = UPPER(SUBSTRING(@str, n,1)) Collate Latin1_General_CS_AI AND n > 1 THEN ' ' + SUBSTRING(@str, n,1) ELSE SUBSTRING(@str, n,1) END FROM Tally FOR XML PATH ('')),1,0,'') SELECT * FROM dbo.udf_Split_Capitals_In_Str ('HelloWorld') SELECT T.* , Fixed_Name.New_Str FixedName FROM ( SELECT Id= 1 , Name = 'DonaldTrump' UNION ALL SELECT Id= 2 , Name = 'HilaryClinton' ) T CROSS APPLY dbo.udf_Split_Capitals_In_Str (T.Name) Fixed_Name