Espressioni regolari di SQL Server in T-SQL


127

Esiste una libreria di espressioni regolari scritta in T-SQL (nessun CLR, nessun SPT-SQL puro esteso ) per SQL Server e che dovrebbe funzionare con l'hosting condiviso?

Modificare:

  • Grazie, so di PATINDEX, LIKE, xp_ spse soluzioni CLR
  • So anche che non è il posto migliore per regex, la domanda è teorica :)
  • Sono accettate anche funzionalità ridotte

2
Anch'io ho questa domanda. So che un database non è il posto migliore per avere questo, ma la realtà è che altre soluzioni richiedono autorizzazioni di amministratore SQL per riconfigurare il server. Sfortunatamente, alcuni dei nostri clienti non sceglieranno di abilitare CLR, ecc. E siamo bloccati a soluzioni solo per database.
Paul Draper,

@PaulDraper e xnagyg: perché escludere SQLCLR? È il mezzo più appropriato per ottenere espressioni regolari nelle query. E perché alcuni dei tuoi clienti dovrebbero scegliere di non abilitare CLR? Devo ancora trovare un motivo valido . Certo, sento "sicurezza" e "prestazioni", ma queste sono ragioni fasulle che sono il risultato della non comprensione di come funziona SQLCLR e come può essere limitato.
Solomon Rutzky il

3
@srutzky: la maggior parte dei provider di hosting condiviso non consente CLR. Dovresti chiedere loro di "sicurezza" e "performance" :)
xnagyg,

@xnagyg Certo, posso chiederne alcuni. Tuttavia, indicare il comportamento di un gruppo non risponde in alcun modo alla domanda "esiste un motivo valido " per quel comportamento. Potrebbe essere altrettanto facile che tutti quei provider di hosting condiviso impostino la loro politica sulla base dello stesso malinteso. E, se non altro, il semplice fatto che non tutti non consentano SQLCLR in realtà supporta l'idea che non ci sia un problema più dell'idea che ci sia un problema poiché se tali problemi esistessero, i provider che consentono SQLCLR sperimenterebbero quei problemi e smetterei di permetterlo.
Solomon Rutzky il

@xnagyg Inoltre, dovrei chiarire che sto parlando in termini di assiemi contrassegnati come SAFEe non contrassegnati come uno EXTERNAL_ACCESSo UNSAFE(poiché capisco perché questi ultimi 2 set di autorizzazioni sarebbero problematici per un ambiente di hosting condiviso). Database SQL V12 di Microsoft Azure (ovvero la nuova versione alla fine del 2014), che è un ambiente condiviso, consente gli assembly contrassegnati come SAFE(e caricati tramite FROM 0x...anziché da una DLL poiché non è possibile caricare una DLL). Ma SAFEè tutto ciò che serve per le espressioni regolari e MOLTE altre funzioni molto utili.
Solomon Rutzky,

Risposte:


77

Che ne dici della funzione PATINDEX ?

La corrispondenza del modello in TSQL non è una libreria regex completa, ma fornisce le basi.

(Da libri 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]).

7
Per almeno un decennio (SQL Server 2005+), LIKEha supportato tutto ciò che PATINDEXfa. Non so prima ...
TJ Crowder,

1
Tuttavia, ciò non mi consente di specificare un modello che corrisponda, diciamo, a un numero variabile di lettere ASCII. %corrisponde a 0 o più caratteri (a prescindere), [...]corrisponde a uno solo e non c'è nulla in mezzo.
Martijn Pieters

LIKE è uguale a PATINDEX> 0
Reversed Engineer

21

Se qualcuno è interessato all'utilizzo di regex con CLR, ecco una soluzione. La funzione seguente (C # .net 4.5) restituisce 1 se il modello è abbinato e 0 se il modello non è abbinato. Lo uso per contrassegnare le righe nelle query secondarie. L'attributo SQLfunction indica a SQL Server che questo metodo è l'UDF effettivo che verrà utilizzato da SQL Server. Salvare il file come dll in un luogo in cui è possibile accedervi da 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;
        }
    }
}

In Management Studio importare il file dll tramite programmabilità - assembly - nuovo assembly

Quindi eseguire questa query:

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

Quindi si dovrebbe avere accesso completo alla funzione tramite il database in cui è stato memorizzato l'assembly.

Quindi utilizzare nelle query in questo modo:

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

Esistono alcune corrispondenze di pattern di base disponibili usando LIKE, dove% corrisponde a qualsiasi numero e combinazione di caratteri, _ corrisponde a qualsiasi carattere e [abc] potrebbe corrispondere a, b o c ... Sono disponibili ulteriori informazioni sul sito MSDN .


5

Se si utilizza SQL Server 2016 o versioni successive, è possibile utilizzare sp_execute_external_scriptinsieme a R. Dispone di funzioni per le ricerche di espressioni regolari, come grepe grepl.

Ecco un esempio per gli indirizzi e-mail. Interrogherò alcune "persone" tramite il motore di database di SQL Server, passerò i dati per quelle persone a R, lascerò che R decida quali persone hanno indirizzi e-mail non validi e ho R che restituisce quel sottoinsieme di persone a SQL Server. Le "persone" provengono dalla [Application].[People]tabella nel [WideWorldImporters]database di esempio. Vengono passati al motore R come un frame di dati denominato InputDataSet. R usa la funzione grepl con l'operatore "non" (punto esclamativo!) Per trovare quali persone hanno indirizzi e-mail che non corrispondono al modello di ricerca della stringa 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)))

Si noti che le funzionalità appropriate devono essere installate sull'host di SQL Server. Per SQL Server 2016, si chiama "SQL Server R Services". Per SQL Server 2017, è stato rinominato "SQL Server Machine Learning Services".

Considerazioni conclusive L'implementazione Microsoft di SQL (T-SQL) non ha il supporto nativo per RegEx. Questa soluzione proposta potrebbe non essere più desiderabile per l'OP rispetto all'uso di una procedura memorizzata CLR. Ma offre un modo aggiuntivo per affrontare il problema.


4

Nel caso in cui qualcun altro stia ancora esaminando questa domanda, http://www.sqlsharp.com/ è un modo semplice e gratuito per aggiungere funzioni CLR di espressioni regolari nel database.


3
Ancora una volta, io sono una soluzione CLR - non quello che l'OP ha richiesto
Ingegnere invertito

10
@DaveBoltman: nel 2008 ha posto la domanda. Le persone lo cercano a volte e si imbattono in questa domanda senza voler evitare il CLR. Questo mi ha aiutato e potrebbe aiutarli.
John Fisher,

Certo, sono d'accordo con te @JohnFisher - è una risposta utile per qualcuno che usa CLR. Ma nel 2015 vorremmo ancora una soluzione SQL nel nostro progetto SQL (senza CLR) per vari motivi, proprio come l'OP nel 2008. L'anno non importa :) Ad esempio, la batteria della tua auto è stata rilasciata in 1859 . Ma ti piacerebbe comunque evitare di utilizzare batterie più moderne come le batterie NiMH rilasciate più di 100 anni dopo, per vari motivi (come la possibilità di permettersi un'auto affatto :)
Ingegnere invertito

2
@DaveBoltman: hai perso la parte in cui "Le persone cercano questo a volte e si imbattono in questa domanda senza voler evitare CLR". Era il punto chiave.
John Fisher,

certo - hai ragione @JohnFisher, l'hai detto tu. Sono contento che ti abbia aiutato, e sono sicuro che aiuterà anche gli altri
Ingegnere invertito,

2

È possibile utilizzare le funzionalità delle espressioni regolari VBScript mediante l'automazione OLE. Questo è molto meglio del sovraccarico di creazione e manutenzione di un assieme. Assicurati di passare attraverso la sezione dei commenti per ottenere una versione modificata migliore di quella principale.

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;

In caso di SQL Server blocked access to procedure 'sys.sp_OACreate'...errore, utilizzare sp_reconfigureper abilitare Ole Automation Procedures. (Sì, sfortunatamente si tratta di una modifica del livello del server!)

Maggiori informazioni sul Testmetodo sono disponibili qui

Buona codifica


sry, so che questo è vecchio, MA: Perché VBScript tramite OLE è "molto meglio" di CLR? Se pensi SOLO alla manutenzione, POTREBBE avere ragione, MA che dire delle prestazioni?
dolce

1
@swe Per "molto meglio", mi riferivo al tempo risparmiato a causa del sovraccarico di creazione e manutenzione di un assembly .NET proprio per questo scopo.
James Poulose,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.