Обходной путь регулярного выражения SQL Server в T-SQL? - PullRequest
4 голосов
/ 26 августа 2011

У меня есть некоторый код SQLCLR для работы с регулярными выражениями. Но теперь, когда он переносится в Azure, который не позволяет SQLCLR, это не так. Мне нужно найти способ сделать регулярное выражение в чистом T-SQL.

Службы основных данных недоступны, поскольку у нас имеется версия MSSQL для разработчиков, отличная от R2.

Все идеи оценены, спасибо.

Примеры соответствия регулярных выражений, которые требуют обработки (отбраковано из regexlib и других мест за последние несколько лет)

адрес электронной почты

^[\w-]+(\.[\w-]+)*@([a-z0-9-]+(\.[a-z0-9-]+)*?\.[a-z]{2,6}|(\d{1,3}\.){3}\d{1,3})(:\d{4})?$

1012 долларов * *

^(\$)?(([1-9]\d{0,2}(\,\d{3})*)|([1-9]\d*)|(0))(\.\d{2})?$

* 1015 URI *

^(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$

одна цифра

^\d$

Процент * * тысяча двадцать один

^-?[0-9]{0,2}(\.[0-9]{1,2})?$|^-?(100)(\.[0]{1,2})?$

обозначение высоты

^\d?\d'(\d|1[01])"$

цифры от 1 1000

^([1-9]|[1-9]\d|1000)$

номера кредитных карт

^((4\d{3})|(5[1-5]\d{2})|(6011))-?\d{4}-?\d{4}-?\d{4}|3[4,7]\d{13}$

список лет

^([1-9]{1}[0-9]{3}[,]?)*([1-9]{1}[0-9]{3})$

дней недели

^(Sun|Mon|(T(ues|hurs))|Fri)(day|\.)?$|Wed(\.|nesday)?$|Sat(\.|urday)?$|T((ue?)|(hu?r?))\.?$

время на 12 часовых часах

(?<Time>^(?:0?[1-9]:[0-5]|1(?=[012])\d:[0-5])\d(?:[ap]m)?)

время на 24-часовых часах

^(?:(?:(?:0?[13578]|1[02])(\/|-|\.)31)\1|(?:(?:0?[13-9]|1[0-2])(\/|-|\.)(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:0?2(\/|-|\.)29\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\/|-|\.)(?:0?[1-9]|1\d|2[0-8])\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$

номера телефонов США

^\(?[\d]{3}\)?[\s-]?[\d]{3}[\s-]?[\d]{4}$

Ответы [ 2 ]

4 голосов
/ 26 августа 2011

К сожалению, вы не сможете переместить свои функции CLR в SQL Azure.Вам нужно будет либо использовать обычные строковые функции (PATINDEX, CHARINDEX, LIKE и т. Д.), Либо выполнить эти операции вне базы данных.

EDIT Добавление некоторой информации для добавленных примеровна вопрос.

Адрес электронной почты

Этот вопрос всегда противоречив, потому что люди не согласны с тем, какую версию RFC они хотят поддержать.Например, оригинал не поддерживал апострофы (или, по крайней мере, люди настаивают на том, что это не так - я не выкопал его из архивов и не читал сам, по общему признанию), и его приходится часто расширять для новыхTLD (один раз для 4-буквенных TLD, таких как .info, затем снова для 6-буквенных TLD, таких как .museum).Я часто слышал, что достаточно знающие люди утверждают, что совершенная проверка электронной почты невозможна, и, ранее работая в поставщике услуг электронной почты, я могу сказать вам, что это была постоянно меняющаяся цель.Но для самых простых подходов см. Вопрос Проверка подлинности электронной почты TSQL (без регулярных выражений) .

Одна цифровая цифра

Вероятно, самая простая изСвязка:

WHERE @s LIKE '[0-9]';

Номера кредитных карт

Предполагается, что вы удаляете тире и пробелы, что вы должны сделать в любом случае.Обратите внимание, что это не фактическая проверка алгоритма номера кредитной карты, чтобы убедиться, что сам номер действительно действителен, просто он соответствует общему формату (AmEx = 15 цифр, начинающихся с 3, остальные 16 цифр - Visaначинается с 4, MasterCard начинается с 5, Discover начинается с 6, и я думаю, что есть один, который начинается с 7 (хотя это могут быть просто подарочные карты):

WHERE @s + ' ' LIKE '[3-7]'+ REPLICATE('[0-9]', 14) + '[0-9 ]';

Если выЕсли вы хотите быть немного более точным в ценах многословности, вы можете сказать:

WHERE (LEN(@s) = 15 AND @s LIKE '3'     + REPLICATE('[0-9]', 14))
   OR (LEN(@s) = 16 AND @s LIKE '[4-7]' + REPLICATE('[0-9]', 15));

номера телефонов США

Опять же, если высобираюсь убрать скобки, тире и пробелы в первую очередь.Уверен, что код США не может начинаться с 1;если есть другие правила, я их не знаю.

WHERE @s LIKE '[2-9]' + REPLICATE('[0-9]', 9);

-----

Я не собираюсь идти дальше, потому чтоМногие другие выражения, которые вы определили, могут быть экстраполированы из вышеприведенного.Надеюсь, это даст вам начало.Вы должны быть в состоянии Google для некоторых других, чтобы видеть, как другие люди копировали образцы с T-SQL.Некоторые из них (например, дни недели), вероятно, можно просто сравнить с таблицей - кажется чрезмерным делать сопоставление с образцом вторжения для набора из 7 возможных значений.Аналогично списку из 1000 чисел или лет это гораздо проще (и, вероятно, более эффективно) проверить, находится ли числовое значение в таблице, а не преобразовать его в строку, и посмотреть, соответствует ли оно некоторому шаблону.

Еще раз скажу, что многое из этого будет намного лучше, если вы сможете очистить и проверить данные, прежде чем они попадут в базу данных.Вы должны стремиться делать это везде, где это возможно, потому что без CLR вы просто не сможете создать мощный RegEx внутри SQL Server.

3 голосов
/ 26 августа 2011

Кен Хендерсон (Ken Henderson) писал о способах репликации RegEx без CLR , но они требуют процедур sp_OA *, которые даже менее вероятно когда-либо увидят свет в Azure, чем CLR.В большинстве других статей, которые вы найдете в Интернете, используется подход, аналогичный подходу Кена, или комплексное использование встроенных строковых функций.

Какие части RegEx конкретно вы пытаетесь тиражировать?Можете ли вы показать пример ввода / вывода одной из ваших функций?Возможно, будет легко конвертировать, чтобы получить аналогичные результаты, используя встроенные строковые функции, такие как PATINDEX.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...