Вот подход, основанный на множествах, с использованием синтаксиса SQL 2005 (было бы немного проще с SQL 2008, но вы не указали). Кроме того, если у вас есть таблица чисел, можно вырезать большую ее часть.
Без зацикливания, без дубликатов и должно быть почти мгновенным (при условии, что целевой столбец проиндексирован).
DECLARE @intMax integer
SET @intMax = 5
INSERT INTO TSTRINGS
SELECT q.nString
FROM ( SELECT ROW_NUMBER() OVER (ORDER BY (newID())) AS N2,
RIGHT(REPLICATE('0', 5) + CONVERT(varchar(5), N), 5) as nString
FROM --the subquery below could be replaced by a numbers table
(SELECT TOP 100000
ROW_NUMBER() OVER (ORDER BY (ac1.Object_ID))-1 AS N
FROM Master.sys.columns ac1
CROSS JOIN Master.sys.columns ac2
CROSS JOIN Master.sys.columns ac3) numbers
WHERE RIGHT(REPLICATE('0', 5) + CONVERT(varchar(5), N), 5)
NOT IN (SELECT nString FROM TSTRINGS) --check to see if reused
) q
WHERE q.N2 <= @intMax