SQL Server Wyrażenia regularne w T-SQL

127

Czy istnieje biblioteka wyrażeń regularnych napisana w języku T-SQL (bez środowiska CLR, bez rozszerzonego SP, czystego języka T-SQL) dla programu SQL Server, która powinna działać w przypadku hostingu współdzielonego?

Edytować:

  • Dzięki, wiem o PATINDEX, LIKE, xp_ spsoraz rozwiązania CLR
  • Wiem też, że to nie jest najlepsze miejsce na regex, pytanie jest teoretyczne :)
  • Dopuszczalna jest również ograniczona funkcjonalność
xnagyg
źródło
2
Ja też mam to pytanie. Wiem, że baza danych nie jest najlepszym miejscem do tego, ale rzeczywistość jest taka, że ​​inne rozwiązania wymagają uprawnień administratora SQL do rekonfiguracji serwera. Niestety, niektórzy z naszych klientów nie zdecydują się na włączenie CLR itp., A my jesteśmy skazani na rozwiązania oparte wyłącznie na bazie danych.
Paul Draper,
@PaulDraper i xnagyg: dlaczego wykluczyć SQLCLR? Jest to najbardziej odpowiedni sposób uzyskiwania wyrażeń regularnych w zapytaniach. I dlaczego niektórzy z Twoich klientów mieliby nie włączać CLR? Nie znalazłem jeszcze ważnego powodu. Jasne, słyszę „bezpieczeństwo” i „wydajność”, ale to są fałszywe powody, które wynikają z niezrozumienia, jak działa SQLCLR i jak można go ograniczyć.
Solomon Rutzky
3
@srutzky: większość współdzielonych dostawców hostingu nie zezwala na CLR. Powinieneś zapytać ich o "bezpieczeństwo" i "wydajność" :)
xnagyg
@xnagyg Jasne, mogę o kilka zapytać. Jednak wskazanie na zachowanie grupy w żaden sposób nie odpowiada na pytanie „czy istnieje ważny powód” takiego zachowania. Równie łatwo mogłoby się zdarzyć, że wszyscy ci dostawcy hostingu współdzielonego ustalają swoje zasady na podstawie tego samego nieporozumienia. I, jeśli nic więcej, prosty fakt, że nie wszystkie z nich zabraniają SQLCLR, w rzeczywistości wspiera ideę, że nie ma problemu bardziej niż idea, że ​​problem istnieje, ponieważ gdyby te problemy istniały, dostawcy, którzy zezwalają na SQLCLR, doświadczaliby te problemy i przestaliby na to pozwalać.
Solomon Rutzky,
@xnagyg Powinienem również wyjaśnić, że mówię o zespołach oznaczonych jako SAFEi nie oznaczonych jako albo EXTERNAL_ACCESSlub UNSAFE(ponieważ rozumiem, dlaczego te 2 ostatnie zestawy uprawnień byłyby problematyczne w przypadku współdzielonego środowiska hostingu). Microsoft Azure SQL Database V12 (tj. Nowa wersja z końca 2014 r.), Która jest środowiskiem współdzielonym, zezwala na zestawy oznaczone jako SAFE(i ładowane za pośrednictwem FROM 0x...zamiast z biblioteki DLL, ponieważ nie można przesłać biblioteki DLL). Ale SAFEto wszystko, czego potrzeba do wyrażeń regularnych i WIELE innych bardzo przydatnych funkcji.
Solomon Rutzky

Odpowiedzi:

77

A co z funkcją PATINDEX ?

Dopasowywanie wzorców w TSQL nie jest pełną biblioteką wyrażeń regularnych, ale zapewnia podstawy.

(Z Books Online)

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]).
Eric Z Beard
źródło
7
Od co najmniej dekady (SQL Server 2005+) LIKEobsługuje wszystko, co PATINDEXrobi. Nie wiem o tym wcześniej ...
TJ Crowder,
1
Jednak to nie pozwala mi określić wzorca, który pasuje, powiedzmy, do zmiennej liczby liter ascii. %dopasowuje 0 lub więcej znaków (niezależnie), [...]dopasowuje tylko jeden i nie ma nic pomiędzy.
Martijn Pieters
LIKE to to samo, co PATINDEX> 0
Reversed Engineer
21

Jeśli ktoś jest zainteresowany używaniem wyrażenia regularnego z CLR, oto rozwiązanie. Funkcja poniżej (C # .net 4.5) zwraca 1, jeśli wzorzec jest dopasowany, i 0, jeśli wzorzec nie jest dopasowany. Używam go do oznaczania linii w zapytaniach podrzędnych. Atrybut funkcji SQL informuje serwer sql, że ta metoda jest faktycznym UDF, którego będzie używał serwer SQL. Zapisz plik jako dll w miejscu, do którego masz dostęp z Management Studio.

// 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;
        }
    }
}

W studiu zarządzania zaimportuj plik dll przez programowalność - zestawy - nowy zespół

Następnie uruchom to zapytanie:

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

Następnie powinieneś mieć pełny dostęp do funkcji za pośrednictwem bazy danych, w której zapisałeś zestaw.

Następnie użyj w zapytaniach takich jak:

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
Matt Farguson
źródło
14

Istnieje kilka podstawowych dopasowań wzorców dostępnych za pomocą funkcji LIKE, gdzie% pasuje do dowolnej liczby i kombinacji znaków, _ pasuje do dowolnego znaku, a [abc] może dopasować a, b lub c ... Więcej informacji można znaleźć w witrynie MSDN .

Steven Murawski
źródło
5

Jeśli korzystasz z SQL Server 2016 lub nowszego, możesz używać sp_execute_external_scriptrazem z R. Ma funkcje do wyszukiwania wyrażeń regularnych, takie jak grepi grepl.

Oto przykład adresów e-mail. Zapytam kilka „osób” za pośrednictwem silnika bazy danych SQL Server, przekażę dane tych osób do R, pozwolę R zdecydować, które osoby mają nieprawidłowe adresy e-mail i pozwolę R przekazać z powrotem podzbiór osób do SQL Server. „Osoby” pochodzą z [Application].[People]tabeli w [WideWorldImporters]przykładowej bazie danych. Są przekazywane do silnika języka R jako ramka danych o nazwie InputDataSet. R używa funkcji grepl z operatorem „not” (wykrzyknik!), Aby znaleźć osoby, których adresy e-mail nie pasują do wzorca wyszukiwania ciągu 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)))

Zwróć uwagę, że odpowiednie funkcje muszą być zainstalowane na hoście SQL Server. W przypadku programu SQL Server 2016 nosi nazwę „Usługi SQL Server R”. W przypadku programu SQL Server 2017 jego nazwa została zmieniona na „SQL Server Machine Learning Services”.

Uwagi końcowe Implementacja SQL (T-SQL) firmy Microsoft nie obsługuje natywnej obsługi wyrażeń regularnych. To proponowane rozwiązanie może nie być bardziej pożądane dla OP niż użycie procedury składowanej CLR. Ale oferuje dodatkowy sposób podejścia do problemu.

Dave Mason
źródło
4

Na wypadek, gdyby ktokolwiek jeszcze szukał tego pytania, http://www.sqlsharp.com/ to darmowy, łatwy sposób na dodanie funkcji CLR wyrażeń regularnych do bazy danych.

John Fisher
źródło
3
Po raz kolejny nie jest to rozwiązanie CLR - a nie to, o co prosił OP
Reversed Engineer
10
@DaveBoltman: Zadał to pytanie w 2008 roku. Ludzie czasami tego szukają i natrafiają na to pytanie, nie chcąc uniknąć CLR. To mi pomogło i może im pomóc.
John Fisher,
Oczywiście, zgadzam się z tobą @JohnFisher - to jest pomocnym rozwiązaniem dla kogoś, przy użyciu CLR. Ale w 2015 roku nadal chcielibyśmy, aby nasz projekt SQL zawierał tylko SQL (bez CLR) z różnych powodów, tak jak w przypadku OP w 2008 roku. Rok nie ma znaczenia :) Np. Akumulator w Twoim samochodzie został wydany w 1859 . Ale nadal chciałbyś uniknąć używania bardziej nowoczesnych akumulatorów, takich jak akumulatory NiMH wypuszczone ponad 100 lat później, z różnych powodów (np. W ogóle stać cię na samochód :)
Reversed Engineer
2
@DaveBoltman: Przegapiłeś część, w której „Ludzie czasami tego szukają i natrafiają na to pytanie bez chęci uniknięcia CLR”. To był kluczowy punkt.
John Fisher
jasne - masz rację @JohnFisher, tak powiedziałeś. Cieszę się, że ci pomogło i jestem pewien, że pomoże też innym
Reversed Engineer
2

Za pomocą automatyzacji OLE można używać funkcji wyrażeń regularnych VBScript. Jest to o wiele lepsze niż obciążenie związane z tworzeniem i utrzymaniem zespołu. Upewnij się, że przejrzałeś sekcję komentarzy, aby uzyskać lepszą zmodyfikowaną wersję głównej.

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;

Jeśli pojawi się SQL Server blocked access to procedure 'sys.sp_OACreate'...błąd, użyj, sp_reconfigureaby włączyć Ole Automation Procedures. (Tak, niestety jest to zmiana na poziomie serwera!)

Więcej informacji o Testmetodzie znajduje się tutaj

Miłego kodowania

James Poulose
źródło
sry, wiem, że to jest stare, ALE: Dlaczego VBScript przez OLE jest „o wiele lepszy” niż CLR? Jeśli myślisz TYLKO o utrzymaniu, MOŻESZ mieć rację, ALE co z wydajnością?
swe
1
@swe Mówiąc „o wiele lepiej”, odnosiłem się do czasu zaoszczędzonego dzięki kosztom związanym z tworzeniem i utrzymywaniem zestawu .NET tylko w tym celu.
James Poulose