SQL Server Регулярні вирази в T-SQL


127

Чи є бібліотека регулярних виразів, написана в T-SQL (немає CLR, не розширений SP, чистий T-SQL) для SQL Server, і яка повинна працювати з спільним хостингом?

Редагувати:

  • Спасибі, я знаю про те PATINDEX, LIKE, xp_ spsі рішення CLR
  • Я також знаю, що це не найкраще місце для регулярного виразу, питання теоретичне :)
  • Знижена функціональність також приймається

2
У мене теж є це питання. Я знаю, що база даних - це не найкраще місце для цього, але реальність полягає в тому, що інші рішення вимагають дозволу адміністратора SQL для переналаштування сервера. На жаль, деякі наші клієнти не вирішать ввімкнути CLR тощо, і ми дотримуємося лише рішень для баз даних.
Пол Дрейпер

@PaulDraper та xnagyg: чому виключають SQLCLR? Це найбільш підходящий засіб отримання регулярних виразів у запитах. І чому деякі з ваших клієнтів вирішили не включати CLR? Я до сих пір не траплялися на дійсну причину. Звичайно, я чую "безпеку" та "продуктивність", але це хибні причини, які є наслідком нерозуміння того, як працює SQLCLR і як його можна обмежити.
Соломон Руцький

3
@srutzky: Більшість провайдерів хостингу не дозволяє CLR. Ви повинні запитати їх про "безпеку" та "продуктивність" :)
xnagyg

@xnagyg Звичайно, я можу запитати декілька. Однак вказівка ​​на поведінку групи жодним чином не стосується питання "чи є поважна причина" такої поведінки. Так само легко може бути те, що всі ці спільні хостинг-провайдери встановлюють свою політику, виходячи з того самого непорозуміння. І, якщо нічого іншого, простий факт, що не всі вони забороняють SQLCLR, насправді підтримує ідею, що це не проблема більше, ніж ідея виникнення проблеми, оскільки якби ці проблеми існували, то провайдери, які дозволяють SQLCLR, відчували б ці проблеми і перестали б це дозволяти.
Соломон Руцький

@xnagyg Також я повинен уточнити, що я виступаю з точки зору зборів, позначених як, SAFEа не позначених як EXTERNAL_ACCESSабо UNSAFE(як я розумію, чому ці два останніх набору дозволів були б проблематичними для спільного середовища хостингу). Microsoft Azure SQL Database V12 (тобто нова версія станом на кінець 2014 р.), Яка є спільним середовищем, дозволяє складанням, позначеним як SAFE(і завантажуються через FROM 0x...DLL, оскільки ви не можете завантажити DLL). Але SAFEце все, що потрібно для регулярних виразів та багато інших дуже корисних функцій.
Соломон Руцький

Відповіді:


77

Як щодо функції PATINDEX ?

Відповідність шаблонів у TSQL не є повною бібліотекою регулярних виразів, але вона дає основи.

(З книг онлайн)

Wildcard  Meaning  
% Any string of zero or more characters.

_ Any single character.

[ ] Any single character within the specified range 
    (for example, [a-f]) or set (for example, [abcdef]).

[^] Any single character not within the specified range 
    (for example, [^a - f]) or set (for example, [^abcdef]).

7
Принаймні десятиліття (SQL Server 2005+) LIKEпідтримував усі дії PATINDEX. Не знаю про це до цього…
TJ Crowder

1
Але це не дозволяє мені вказати шаблон, який відповідає, скажімо, змінній кількості літер ascii. %відповідає 0 або більше символів (незалежно), [...]відповідає лише одному, і між ними немає нічого.
Martijn Pieters

LIKE - це те саме, що PATINDEX> 0
інженер з

21

Якщо хтось зацікавлений у використанні регулярного вираження з CLR, ось рішення. Функція нижче (C # .net 4.5) повертає 1, якщо шаблон узгоджено, і 0, якщо шаблон не збігається. Я використовую його для тегування рядків у підзапитах. Атрибут SQLfunction повідомляє серверу sql, що цей метод є фактичним UDF, який використовуватиме SQL-сервер. Збережіть файл як dll в місці, де ви можете отримати доступ до нього зі студії управління.

// default using statements above
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Text.RegularExpressions;

namespace CLR_Functions
{   
    public class myFunctions
    {
        [SqlFunction]
        public static SqlInt16 RegexContain(SqlString text, SqlString pattern)
        {            
            SqlInt16 returnVal = 0;
            try
            {
                string myText = text.ToString();
                string myPattern = pattern.ToString();
                MatchCollection mc = Regex.Matches(myText, myPattern);
                if (mc.Count > 0)
                {
                    returnVal = 1;
                }
            }
            catch
            {
                returnVal = 0;
            }

            return returnVal;
        }
    }
}

В студію управління імпортуйте файл dll за допомогою програмованості - асамблей - нової збірки

Потім запустіть цей запит:

CREATE FUNCTION RegexContain(@text NVARCHAR(50), @pattern NVARCHAR(50))
RETURNS smallint 
AS
EXTERNAL NAME CLR_Functions.[CLR_Functions.myFunctions].RegexContain

Тоді ви повинні мати повний доступ до функції через базу даних, в якій зберігалася збірка.

Потім використовуйте такі запити:

SELECT * 
FROM 
(
    SELECT
        DailyLog.Date,
        DailyLog.Researcher,
        DailyLog.team,
        DailyLog.field,
        DailyLog.EntityID,
        DailyLog.[From],
        DailyLog.[To],
        dbo.RegexContain(Researcher, '[\p{L}\s]+') as 'is null values'
    FROM [DailyOps].[dbo].[DailyLog]
) AS a
WHERE a.[is null values] = 0

14

Існує деяка основна відповідність шаблону за допомогою LIKE, де% відповідає будь-якій кількості та комбінації символів, _ відповідає будь-якому одному символу, а [abc] може відповідати а, b або c ... Більше інформації на сайті MSDN .


5

Якщо ви використовуєте SQL Server 2016 або новіші версії, ви можете використовувати sp_execute_external_scriptразом з R. У ньому є функції для пошуку в регулярних виразках, таких як grepі grepl.

Ось приклад електронних адрес. Я запитую «людей» через двигун баз даних SQL Server, передаю дані для цих людей R, нехай R вирішить, які люди мають недійсні адреси електронної пошти, і R поверне цю підмножину людей на SQL Server. "Люди" - з [Application].[People]таблиці в [WideWorldImporters]вибірковій базі даних. Вони передаються двигуну R як названий кадр даних InputDataSet. R використовує функцію grepl з оператором "не" (знак оклику!) Для пошуку людей, які мають адреси електронної пошти, які не відповідають шаблону пошуку рядка RegEx.

EXEC sp_execute_external_script 
 @language = N'R',
 @script = N' RegexWithR <- InputDataSet;
OutputDataSet <- RegexWithR[!grepl("([_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,4}))", RegexWithR$EmailAddress), ];',
 @input_data_1 = N'SELECT PersonID, FullName, EmailAddress FROM Application.People'
 WITH RESULT SETS (([PersonID] INT, [FullName] NVARCHAR(50), [EmailAddress] NVARCHAR(256)))

Зверніть увагу, що відповідні функції повинні бути встановлені на хості SQL Server. Для SQL Server 2016 він називається "Послуги SQL Server R". Для SQL Server 2017 він був перейменований на "Служби навчання машинного навчання SQL Server".

Закриття думки Реалізація SQL (T-SQL) Microsoft не має вбудованої підтримки для RegEx. Запропоноване рішення може бути не більш бажаним для ОП, ніж використання збереженої CLR процедури. Але це пропонує додатковий спосіб підійти до проблеми.


4

У випадку, якщо хтось ще не дивиться на це питання, http://www.sqlsharp.com/ - це безкоштовний, простий спосіб додати CLR функції регулярного виразу у вашу базу даних.


3
Ще раз - це рішення CLR - не те, про що вимагала ОП
інженер, що

10
@DaveBoltman: Він задав це питання в 2008 році. Люди шукають це іноді і стикаються з цим питанням, не бажаючи уникати CLR. Це допомогло мені і, можливо, їм допоможе.
Джон Фішер

Звичайно, я згоден з вами @JohnFisher - це є корисним відповіддю для кого - то з допомогою CLR. Але в 2015 році ми все ще любимо рішення, яке стосується лише SQL, в нашому проекті SQL (без CLR) з різних причин, як і в ОП 2008 року. Рік не має значення :) Наприклад, акумулятор у вашій машині був випущений у 1859 рік . Але ви все-таки хочете уникати використання більш сучасних акумуляторів, таких як NiMH батареї, випущені через 100 років пізніше, з різних причин (наприклад, взагалі можна дозволити собі автомобіль :)
Інвертор

2
@DaveBoltman: Ви пропустили ту частину, де "Люди іноді шукають це, і натрапляють на це питання, не бажаючи уникати CLR". Це було ключовим моментом.
Джон Фішер

впевнений - ти правий @JohnFisher, ти це сказав. Радий, що це допомогло вам, і я впевнений, що він допоможе і іншим
інженер, що

2

Ви можете використовувати функції регулярного вираження VBScript за допомогою OLE Automation. Це набагато краще, ніж витрати на створення та підтримку збірки. Будь ласка, переконайтесь у розділі коментарів, щоб отримати кращу модифіковану версію основного.

http://blogs.msdn.com/b/khen1234/archive/2005/05/11/416392.aspx

DECLARE @obj INT, @res INT, @match BIT;
DECLARE @pattern varchar(255) = '<your regex pattern goes here>';
DECLARE @matchstring varchar(8000) = '<string to search goes here>';
SET @match = 0;

-- Create a VB script component object
EXEC @res = sp_OACreate 'VBScript.RegExp', @obj OUT;

-- Apply/set the pattern to the RegEx object
EXEC @res = sp_OASetProperty @obj, 'Pattern', @pattern;

-- Set any other settings/properties here
EXEC @res = sp_OASetProperty @obj, 'IgnoreCase', 1;

-- Call the method 'Test' to find a match
EXEC @res = sp_OAMethod @obj, 'Test', @match OUT, @matchstring;

-- Don't forget to clean-up
EXEC @res = sp_OADestroy @obj;

Якщо ви отримаєте SQL Server blocked access to procedure 'sys.sp_OACreate'...помилку, використовуйте sp_reconfigureдля ввімкнення Ole Automation Procedures. (Так, на жаль, це зміна рівня сервера!)

Більше інформації про Testметод можна отримати тут

Щасливе кодування


sry, я знаю, це старе, АЛЕ: Чому VBScript через OLE "набагато кращий", ніж CLR? Якщо ви САМО думаєте про технічне обслуговування, ви могли б мати рацію, АЛЕ як щодо продуктивності?
swe

1
@swe 'Краще', я мав на увазі заощаджений час у зв'язку із витратами на створення та підтримку .NET збірки саме для цієї мети.
James Poulose
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.