CLR или регулярные выражения не нужны для чего-то подобного. Подобные проблемы точно , которые NGrams8K были предназначены для решения. Сначала для ускоренного курса на NGrams8K.
Это:
DECLARE @string VARCHAR(100) = 'ABC123XYZ'
SELECT ng.position, ng.token
FROM dbo.NGrams8k(@string, 7) AS ng;
Возвращает:
position token
--------- -----------
1 ABC123X
2 BC123XY
3 C123XYZ
Для идентификации фрагмента букв (AKA подстрока или, в контексте N-грамм , 7-грамм ), которые (1) начинаться с буквы, включает как минимум одно число и не содержит строчных букв, которые вы могли бы использовать NGrams8K, например:
DECLARE @string VARCHAR(100) = 'x96AE0E33CFD5';
SELECT ng.position, ng.token
FROM dbo.ngrams8k(@string,7) AS ng
CROSS APPLY (VALUES(ng.token COLLATE latin1_general_bin2)) AS token(cs)
WHERE token.cs LIKE '[A-Z]%[0-9]%'
AND token.cs NOT LIKE '%[a-z]%';
, который возвращает:
position token
---------- ---------------
4 AE0E33C
5 E0E33CF
7 E33CFD5
Как видите, мы извлекли каждую 7-символьную подстроку, соответствующую вашим требованиям. Кроме того, это будет более эффективным:
SELECT ng.position, ng.token
FROM dbo.ngrams8k(@string,7) AS ng
WHERE (ASCII(LEFT(ng.token,1)) - 65) & 0x7FFF < 26
AND PATINDEX('%[a-z]%',ng.token COLLATE latin1_general_bin2) = 0;
Чтобы лучше понять, что происходит, рассмотрите этот запрос:
DECLARE @string VARCHAR(100) = 'x96AE0E33CFD5';
SELECT ng.position,
ng.token,
isMatch = CASE WHEN token.cs LIKE '[A-Z]%[0-9]%'
AND token.cs NOT LIKE '%[a-z]%' THEN 1 ELSE 0 END
FROM dbo.ngrams8k(@string,7) AS ng
CROSS APPLY (VALUES(ng.token COLLATE latin1_general_bin2)) AS token(cs);
, который возвращает:
position token isMatch
---------- ---------- ---------
1 x96AE0E 0
2 96AE0E3 0
3 6AE0E33 0
4 AE0E33C 1
5 E0E33CF 1
6 0E33CFD 0
7 E33CFD5 1
Вот пример таблицы, в которой вы хотите вернуть только те строки, которые соответствуют вашим критериям:
DECLARE @table TABLE (someId INT IDENTITY, string VARCHAR(100));
INSERT @table(string) VALUES ('!!!!AB1234567'),('c555'),('!!ABC1234ggg')
SELECT t.someId, t.string
FROM @table AS t
WHERE EXISTS
(
SELECT 1
FROM dbo.ngrams8k(t.string,7) AS ng
WHERE (ASCII(LEFT(ng.token,1)) - 65) & 0x7FFF < 26
AND PATINDEX('%[a-z]%',ng.token COLLATE latin1_general_bin2) = 0
);