SQL Server Reguläre Ausdrücke in T-SQL

127

Gibt es eine in T-SQL geschriebene Bibliothek für reguläre Ausdrücke (keine CLR, keine erweiterte SP, reine T-SQL) für SQL Server, die mit Shared Hosting funktionieren sollte?

Bearbeiten:

  • Danke, weiß ich PATINDEX, LIKE, xp_ spsund CLR - Lösungen
  • Ich weiß auch, dass es nicht der beste Ort für Regex ist, die Frage ist theoretisch :)
  • Reduzierte Funktionalität wird ebenfalls akzeptiert
xnagyg
quelle
2
Ich habe auch diese Frage. Ich weiß, dass eine Datenbank nicht der beste Ort dafür ist, aber die Realität ist, dass andere Lösungen SQL-Administratorrechte erfordern, um den Server neu zu konfigurieren. Leider entscheiden sich einige unserer Kunden nicht dafür, CLR usw. zu aktivieren, und wir bleiben bei reinen Datenbanklösungen.
Paul Draper
@PaulDraper und xnagyg: Warum SQLCLR ausschließen? Dies ist das am besten geeignete Mittel, um reguläre Ausdrücke in Abfragen abzurufen. Und warum sollten einige Ihrer Kunden CLR nicht aktivieren? Ich habe noch keinen gültigen Grund gefunden. Sicher, ich höre "Sicherheit" und "Leistung", aber das sind falsche Gründe, die darauf zurückzuführen sind, dass wir nicht verstehen, wie SQLCLR funktioniert und wie es eingeschränkt werden kann.
Solomon Rutzky
3
@srutzky: Die meisten Shared Hosting-Anbieter erlauben keine CLR. Sie sollten sie nach "Sicherheit" und "Leistung" fragen :)
xnagyg
@ xnagyg Klar, ich kann ein paar fragen. Der Hinweis auf das Verhalten einer Gruppe geht jedoch in keiner Weise auf die Frage ein , ob es einen gültigen Grund für dieses Verhalten gibt. Es könnte genauso gut sein, dass alle diese Shared-Hosting-Anbieter ihre Richtlinien auf der Grundlage desselben Missverständnisses festlegen. Und nicht zuletzt die einfache Tatsache, dass nicht alle von ihnen SQLCLR nicht zulassen, unterstützt tatsächlich die Idee, dass es kein Problem mehr gibt als die Idee, dass es ein Problem gibt, denn wenn diese Probleme existieren würden, würden die Anbieter, die SQLCLR zulassen, auftreten diese Probleme und würde aufhören, es zuzulassen.
Solomon Rutzky
@xnagyg Außerdem sollte ich klarstellen, dass ich in Bezug auf Assemblys spreche, die als SAFEoder nicht als EXTERNAL_ACCESSoder gekennzeichnet sind UNSAFE(da ich verstehe, warum diese beiden letztgenannten Berechtigungssätze für eine gemeinsam genutzte Hosting-Umgebung problematisch wären). Microsoft Azure SQL Database V12 (dh die neue Version ab Ende 2014), bei der es sich um eine gemeinsam genutzte Umgebung handelt, ermöglicht Assemblies, die als gekennzeichnet sind SAFE(und über FROM 0x...statt aus einer DLL geladen werden, da Sie keine DLL hochladen können). Aber SAFEist alles, was für reguläre Ausdrücke und viele andere sehr nützliche Funktionen benötigt wird.
Solomon Rutzky

Antworten:

77

Wie wäre es mit der PATINDEX- Funktion?

Der Pattern Matching in TSQL ist keine vollständige Regex-Bibliothek, bietet Ihnen jedoch die Grundlagen.

(Aus Online-Büchern)

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 Bart
quelle
7
Seit mindestens einem Jahrzehnt (SQL Server 2005+) LIKEwird alles unterstützt, was PATINDEXfunktioniert. Ich weiß es vorher nicht ...
TJ Crowder
1
Damit kann ich jedoch kein Muster angeben, das beispielsweise einer variablen Anzahl von ASCII-Buchstaben entspricht. %Entspricht 0 oder mehr Zeichen (unabhängig davon), [...]Entspricht nur einem, und es liegt nichts dazwischen.
Martijn Pieters
LIKE ist dasselbe wie PATINDEX> 0
Reversed Engineer
21

Wenn jemand daran interessiert ist, Regex mit CLR zu verwenden, ist hier eine Lösung. Die folgende Funktion (C # .net 4.5) gibt eine 1 zurück, wenn das Muster übereinstimmt, und eine 0, wenn das Muster nicht übereinstimmt. Ich benutze es, um Zeilen in Unterabfragen zu markieren. Das SQLfunction-Attribut teilt dem SQL Server mit, dass diese Methode die tatsächliche UDF ist, die der SQL Server verwendet. Speichern Sie die Datei als DLL an einem Ort, an dem Sie von Management Studio aus darauf zugreifen können.

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

Im Management Studio importieren Sie die DLL-Datei über Programmierbarkeit - Assemblys - neue Assembly

Führen Sie dann diese Abfrage aus:

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

Dann sollten Sie über die Datenbank, in der Sie die Assembly gespeichert haben, vollständigen Zugriff auf die Funktion haben.

Verwenden Sie dann in Abfragen wie folgt:

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
quelle
14

Durch die Verwendung von LIKE ist ein grundlegender Mustervergleich verfügbar, bei dem% mit einer beliebigen Anzahl und Kombination von Zeichen übereinstimmt, _ mit einem beliebigen Zeichen übereinstimmt und [abc] mit a, b oder c übereinstimmen kann. Weitere Informationen finden Sie auf der MSDN-Site .

Steven Murawski
quelle
5

Wenn Sie SQL Server 2016 oder höher verwenden, können Sie es sp_execute_external_scriptzusammen mit R verwenden. Es verfügt über Funktionen für die Suche nach regulären Ausdrücken, wie z. B. grepund grepl.

Hier ist ein Beispiel für E-Mail-Adressen. Ich werde einige "Personen" über das SQL Server-Datenbankmodul abfragen, die Daten für diese Personen an R übergeben, R entscheiden lassen, welche Personen ungültige E-Mail-Adressen haben, und R diese Teilmenge von Personen an SQL Server zurückgeben lassen. Die "Personen" stammen aus der [Application].[People]Tabelle in der [WideWorldImporters]Beispieldatenbank. Sie werden als benannter Datenrahmen an die R-Engine übergeben InputDataSet. R verwendet die grepl-Funktion mit dem Operator "not" (Ausrufezeichen!), Um herauszufinden, welche Personen E-Mail-Adressen haben, die nicht mit dem RegEx-Zeichenfolgensuchmuster übereinstimmen.

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)))

Beachten Sie, dass die entsprechenden Funktionen auf dem SQL Server-Host installiert sein müssen. Für SQL Server 2016 heißt es "SQL Server R Services". Für SQL Server 2017 wurde es in "SQL Server Machine Learning Services" umbenannt.

Abschließende Gedanken Die Implementierung von SQL (T-SQL) durch Microsoft bietet keine native Unterstützung für RegEx. Diese vorgeschlagene Lösung ist für das OP möglicherweise nicht wünschenswerter als die Verwendung einer gespeicherten CLR-Prozedur. Es bietet jedoch eine zusätzliche Möglichkeit, sich dem Problem zu nähern.

Dave Mason
quelle
4

Falls sich noch jemand mit dieser Frage befasst, ist http://www.sqlsharp.com/ eine kostenlose und einfache Möglichkeit, CLR-Funktionen für reguläre Ausdrücke in Ihre Datenbank aufzunehmen.

John Fisher
quelle
3
Wieder einmal ist es eine CLR-Lösung - nicht das, was das OP verlangt hat
Reversed Engineer
9
@ DaveBoltman: Er hat die Frage 2008 gestellt. Manchmal suchen die Leute danach und stoßen auf diese Frage, ohne CLR vermeiden zu wollen. Das hat mir geholfen und könnte ihnen helfen.
John Fisher
Klar, ich stimme dir zu @JohnFisher - es ist eine hilfreiche Antwort für jemanden, der CLR verwendet. Aber 2015 möchten wir aus verschiedenen Gründen immer noch eine reine SQL-Lösung in unserem SQL-Projekt (keine CLR), genau wie das OP im Jahr 2008. Das Jahr spielt keine Rolle :) ZB wurde die Batterie in Ihrem Auto in freigegeben 1859 . Aber Sie möchten immer noch vermeiden, modernere Batterien wie NiMH-Batterien zu verwenden, die mehr als 100 Jahre später aus verschiedenen Gründen herausgebracht wurden (z. B. um sich überhaupt ein Auto leisten zu können :)
Umgekehrter Ingenieur
2
@ DaveBoltman: Sie haben den Teil verpasst, in dem "Leute manchmal danach suchen und auf diese Frage stoßen, ohne CLR vermeiden zu wollen". Es war der entscheidende Punkt.
John Fisher
sicher - du hast recht @JohnFisher, das hast du gesagt. Ich bin froh, dass es Ihnen geholfen hat, und ich bin sicher, dass es auch anderen helfen wird
Reversed Engineer
2

Sie können VBScript-Funktionen für reguläre Ausdrücke mithilfe von OLE Automation verwenden. Dies ist weitaus besser als der Aufwand für das Erstellen und Verwalten einer Baugruppe. Bitte gehen Sie den Kommentarbereich durch, um eine besser modifizierte Version der Hauptversion zu erhalten.

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;

Wenn Sie eine SQL Server blocked access to procedure 'sys.sp_OACreate'...Fehlermeldung erhalten, sp_reconfigureaktivieren Sie diese Option Ole Automation Procedures. (Ja, leider ist das eine Änderung der Serverebene!)

Weitere Informationen zur TestMethode finden Sie hier

Viel Spaß beim Codieren

James Poulose
quelle
sry, ich weiß, das ist alt, ABER: Warum ist VBScript durch OLE "viel besser" als CLR? Wenn Sie NUR an Wartung denken, KÖNNTEN Sie Recht haben, ABER was ist mit Leistung?
Swe
1
@swe Mit "viel besser" bezog ich mich auf die Zeitersparnis aufgrund des Overheads beim Erstellen und Verwalten einer .NET-Assembly nur für diesen Zweck.
James Poulose