If you end up wanting to use a function I would recommend using an inline table valued function instead of a scalar function that has a while loop inside. The performance of that scalar function is going to degrade quickly as the table gets larger. Here is an example of using an inline table valued function and a tally table so the replacement is set based.
If this was my code I would prefer to use the REPLACE option if that is a possibility.
CREATE FUNCTION [dbo].[StripNonAlphaNumeric_itvf]
(
@OriginalText VARCHAR(8000)
) RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH
E1(N) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
Tally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select STUFF(
(
SELECT SUBSTRING(@OriginalText, t.N, 1)
FROM tally t
WHERE
(
ASCII(SUBSTRING(@OriginalText, t.N, 1)) BETWEEN 48 AND 57 --numbers 0 - 9
OR
ASCII(SUBSTRING(@OriginalText, t.N, 1)) BETWEEN 65 AND 90 --UPPERCASE letters
OR
ASCII(SUBSTRING(@OriginalText, t.N, 1)) BETWEEN 97 AND 122 --LOWERCASE letters
)
AND n <= len(@OriginalText)
FOR XML PATH('')
), 1 ,0 , '') AS CleanedText