Регулярные выражения SQL Server в T-SQL

Существует ли какая-либо библиотека регулярных выражений, написанная на T-SQL (без CLR, без расширенного SP, чистый T-SQL) для SQL Server, которая должна работать с общим хостингом?

Редактировать:

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

person xnagyg    schedule 11.10.2008    source источник
comment
У меня тоже есть этот вопрос. Я знаю, что база данных — не лучшее место для этого, но реальность такова, что другим решениям требуются права администратора SQL для перенастройки сервера. К сожалению, некоторые из наших клиентов не захотят включать CLR и т. д., и мы застряли на решениях только для баз данных.   -  person Paul Draper    schedule 13.03.2013
comment
@PaulDraper и xnagyg: зачем исключать SQLCLR? Это наиболее подходящий способ получения регулярных выражений в запросах. И почему некоторые из ваших клиентов решили не включать CLR? Мне еще предстоит найти уважительную причину. Конечно, я слышал о безопасности и производительности, но это ложные причины, возникающие в результате непонимания того, как работает SQLCLR и как его можно ограничить.   -  person Solomon Rutzky    schedule 05.06.2015
comment
@srutzky: большинство провайдеров общего хостинга не разрешают CLR. Вы должны спросить их о безопасности и производительности :)   -  person xnagyg    schedule 05.06.2015
comment
@xnagyg Конечно, я могу задать несколько вопросов. Однако указание на поведение группы никоим образом не решает вопрос о том, есть ли уважительная причина такого поведения. Вполне может быть, что все эти провайдеры виртуального хостинга устанавливают свою политику на основе одного и того же недоразумения. И, по крайней мере, тот простой факт, что не все из них запрещают SQLCLR, на самом деле поддерживает идею о том, что нет проблемы, больше, чем идея о том, что проблема существует, поскольку если бы эти проблемы действительно существовали, провайдеры, разрешающие SQLCLR, столкнулись бы с этими проблемами и прекратили бы их разрешать.   -  person Solomon Rutzky    schedule 05.06.2015
comment
@xnagyg Кроме того, я должен уточнить, что я говорю о сборках, помеченных как SAFE, а не помеченных как EXTERNAL_ACCESS или UNSAFE (поскольку я понимаю, почему эти два последних набора разрешений будут проблематичными для среды общего хостинга). База данных Microsoft Azure SQL V12 (т. е. новая версия на конец 2014 г.), которая является общей средой, позволяет использовать сборки, помеченные как SAFE (и загружаемые через FROM 0x..., а не из DLL, поскольку вы не можете загрузить DLL). Но SAFE — это все, что нужно для регулярных выражений и МНОЖЕСТВА других очень полезных функций.   -  person Solomon Rutzky    schedule 05.06.2015
comment
@srutzky: к сожалению, в то время (в 2011 году) я не нашел виртуального хостинга с поддержкой CLR. Вместо этого мне удалось использовать полнотекстовый поиск.   -  person xnagyg    schedule 05.06.2015
comment
На случай, если кто-то все еще ищет решение, вот еще один вариант: red-gate.com/simple-talk/sql/t-sql-programming/, который использует процедуру VBScript.RegExp через OLE-автоматизацию из T-SQL.   -  person Reversed Engineer    schedule 15.10.2019
comment
(аналогично ответу Джеймса Пулоса ниже)   -  person Reversed Engineer    schedule 15.10.2019


Ответы (6)


Как насчет функции 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]).
person Eric Z Beard    schedule 13.10.2008
comment
По крайней мере десять лет (SQL Server 2005+) LIKE поддерживает все, что делает PATINDEX. Не знаю, как до этого... - person T.J. Crowder; 09.07.2015
comment
Тем не менее, это не позволяет мне указать шаблон, который соответствует, скажем, переменному количеству букв ascii. % соответствует 0 или более символам (независимо), [...] соответствует только одному, и между ними нет ничего. - person Martijn Pieters; 26.03.2018
comment
LIKE совпадает с PATINDEX › 0 - person Reversed Engineer; 15.10.2019

Если кто-то заинтересован в использовании регулярных выражений с CLR, вот решение. Приведенная ниже функция (C# .net 4.5) возвращает 1, если шаблон соответствует, и 0, если шаблон не соответствует. Я использую его для пометки строк в подзапросах. Атрибут SQLfunction сообщает серверу sql, что этот метод является фактической пользовательской функцией, которую будет использовать сервер 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
person Matt Farguson    schedule 16.06.2015

Существует некоторое базовое сопоставление с образцом, доступное с помощью LIKE, где % соответствует любому числу и комбинации символов, _ соответствует любому одному символу, а [abc] может соответствовать a, b или c... Дополнительная информация о сайт MSDN.

person Steven Murawski    schedule 11.10.2008

Если вы используете 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».

Заключительные мысли Реализация Microsoft SQL (T-SQL) не имеет встроенной поддержки RegEx. Это предлагаемое решение может быть не более желательным для OP, чем использование хранимой процедуры CLR. Но он предлагает дополнительный подход к проблеме.

person Dave Mason    schedule 03.10.2017

На случай, если кто-то еще заинтересуется этим вопросом, http://www.sqlsharp.com/ является бесплатным , простой способ добавления функций CLR регулярных выражений в вашу базу данных.

person John Fisher    schedule 03.06.2015
comment
Еще раз, это решение CLR, а не то, о чем просил ОП. - person Reversed Engineer; 20.07.2015
comment
@DaveBoltman: он задал этот вопрос в 2008 году. Люди иногда ищут это и сталкиваются с этим вопросом, не желая избегать CLR. Это помогло мне и может помочь им. - person John Fisher; 20.07.2015
comment
Конечно, я согласен с вами, @JohnFisher - это это полезный ответ для тех, кто использует CLR. Но в 2015 году мы по разным причинам хотели бы использовать только SQL-решение в нашем проекте SQL (без CLR), как и OP в 2008 году. Год не имеет значения :) Например. батарея в вашем автомобиле была выпущена в 1859 году. Но вы по-прежнему хотели бы избегать использования более современных аккумуляторов, таких как NiMH аккумуляторы, выпущенные более 100 лет спустя, по разным причинам (например, из-за того, что вы вообще можете позволить себе автомобиль :) - person Reversed Engineer; 28.07.2015
comment
@DaveBoltman: Вы пропустили ту часть, где люди иногда ищут это и сталкиваются с этим вопросом, не желая избегать CLR. Это был ключевой момент. - person John Fisher; 28.07.2015
comment
конечно - ты прав, @JohnFisher, ты это сказал. Рад, что помог вам, и я уверен, что это поможет и другим - person Reversed Engineer; 29.07.2015

Вы можете использовать функции регулярных выражений 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 доступны здесь

Удачного кодирования

person James Poulose    schedule 15.10.2012
comment
извините, я знаю, что это старо, НО: почему VBScript через OLE намного лучше, чем CLR? Если вы думаете ТОЛЬКО об обслуживании, вы МОЖЕТЕ быть правы, НО как насчет производительности? - person swe; 19.07.2016
comment
@swe Под «намного лучше» я имел в виду время, сэкономленное из-за накладных расходов на создание и поддержку сборки .NET только для этой цели. - person James Poulose; 19.07.2016