SQL Server Expresiones regulares en T-SQL

127

¿Existe alguna biblioteca de expresiones regulares escrita en T-SQL (sin CLR, no extendida SP, T-SQL puro) para SQL Server, y eso debería funcionar con hosting compartido?

Editar:

  • Gracias, lo que sé de PATINDEX, LIKE, xp_ spsy soluciones CLR
  • También sé que no es el mejor lugar para expresiones regulares, la pregunta es teórica :)
  • También se acepta una funcionalidad reducida.
xnagyg
fuente
2
Yo también tengo esta pregunta. Sé que una base de datos no es el mejor lugar para tener esto, pero la realidad es que otras soluciones requieren permisos de administrador SQL para reconfigurar el servidor. Desafortunadamente, algunos de nuestros clientes no elegirán habilitar CLR, etc., y estamos atascados en soluciones de base de datos solamente.
Paul Draper
@PaulDraper y xnagyg: ¿por qué descartar SQLCLR? Es el medio más apropiado para obtener expresiones regulares en las consultas. ¿Y por qué algunos de sus clientes eligen no habilitar CLR? Todavía tengo que encontrar una razón válida . Claro, escucho "seguridad" y "rendimiento", pero esas son razones falsas que son el resultado de no entender cómo funciona SQLCLR y cómo se puede restringir.
Solomon Rutzky
3
@srutzky: el proveedor de alojamiento más compartido no permite CLR. Debería preguntarles sobre "seguridad" y "rendimiento" :)
xnagyg
@xnagyg Claro, puedo preguntar algunas. Sin embargo, señalar el comportamiento de un grupo de ninguna manera aborda la cuestión de "¿hay una razón válida " para ese comportamiento? Podría ser fácilmente que todos esos proveedores de alojamiento compartido establezcan su política en base al mismo malentendido. Y, por lo menos, el simple hecho de que no todos ellos rechazan SQLCLR en realidad respalda la idea de que no haya un problema más que la idea de que haya un problema, ya que si esos problemas existieran, los proveedores que permiten SQLCLR experimentarían esos problemas y dejarían de permitirlo.
Solomon Rutzky
@xnagyg Además, debo aclarar que estoy hablando en términos de Asambleas marcadas como SAFEy no marcadas como EXTERNAL_ACCESSo UNSAFE(ya que entiendo por qué esos 2 últimos Conjuntos de permisos serían problemáticos para un entorno de alojamiento compartido). Microsoft Azure SQL Database V12 (es decir, la nueva versión a finales de 2014), que es un entorno compartido, permite ensamblados marcados como SAFE(y cargados a través de, en FROM 0x...lugar de desde un archivo DLL, ya que no puede cargar un archivo DLL). Pero SAFEes todo lo que se necesita para las expresiones regulares y MUCHAS otras funciones muy útiles.
Solomon Rutzky

Respuestas:

77

¿Qué tal la función PATINDEX ?

La coincidencia de patrones en TSQL no es una biblioteca de expresiones regulares completa, pero le brinda los conceptos básicos.

(De los libros en línea)

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
fuente
77
Durante al menos una década (SQL Server 2005+), LIKEha admitido todo lo que PATINDEXhace. No sé antes de eso ...
TJ Crowder
1
Sin embargo, esto no me permite especificar un patrón que coincida, digamos, con un número variable de letras ascii. %coincide con 0 o más caracteres (independientemente), [...]coincide con solo uno y no hay nada en el medio.
Martijn Pieters
LIKE es lo mismo que PATINDEX> 0
Ingeniero invertido
21

Si alguien está interesado en usar expresiones regulares con CLR, aquí hay una solución. La siguiente función (C # .net 4.5) devuelve un 1 si el patrón coincide y un 0 si el patrón no coincide. Lo uso para etiquetar líneas en subconsultas. El atributo SQLfunction le dice al servidor SQL que este método es el UDF real que usará el servidor SQL. Guarde el archivo como un archivo DLL en un lugar donde pueda acceder desde el estudio de administración.

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

En Management Studio, importe el archivo dll a través de programabilidad - ensamblados - nuevo ensamblaje

Luego ejecute esta consulta:

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

Entonces debe tener acceso completo a la función a través de la base de datos en la que almacenó el ensamblado.

Luego, use en consultas como esta:

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

Hay algunas coincidencias de patrones básicos disponibles mediante el uso de LIKE, donde% coincide con cualquier número y combinación de caracteres, _ coincide con cualquier carácter y [abc] podría coincidir con a, b o c ... Hay más información en el sitio de MSDN .

Steven Murawski
fuente
5

Si está utilizando SQL Server 2016 o superior, puede usarlo sp_execute_external_scriptjunto con R. Tiene funciones para búsquedas de Expresión regular, como grepy grepl.

Aquí hay un ejemplo para las direcciones de correo electrónico. Consultaré a algunas "personas" a través del motor de base de datos de SQL Server, pasaré los datos de esas personas a R, dejaré que R decida qué personas tienen direcciones de correo electrónico no válidas y que R devuelva ese subconjunto de personas a SQL Server. Las "personas" son de la [Application].[People]tabla en la [WideWorldImporters]base de datos de muestra. Se pasan al motor R como un marco de datos llamado InputDataSet. R usa la función grepl con el operador "no" (¡signo de exclamación!) Para encontrar qué personas tienen direcciones de correo electrónico que no coinciden con el patrón de búsqueda de cadenas 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)))

Tenga en cuenta que las características apropiadas deben instalarse en el host de SQL Server. Para SQL Server 2016, se llama "SQL Server R Services". Para SQL Server 2017, se renombró a "Servicios de aprendizaje automático de SQL Server".

Reflexiones finales La implementación de Microsoft de SQL (T-SQL) no tiene soporte nativo para RegEx. Esta solución propuesta puede no ser más deseable para el OP que el uso de un procedimiento almacenado CLR. Pero sí ofrece una forma adicional de abordar el problema.

Dave Mason
fuente
4

En caso de que alguien más siga analizando esta pregunta, http://www.sqlsharp.com/ es una forma fácil y gratuita de agregar funciones CLR de expresión regular en su base de datos.

John Fisher
fuente
3
Una vez más, soy una solución CLR, no lo que solicitó el OP
ingeniero revertido el
10
@DaveBoltman: hizo la pregunta en 2008. La gente busca esto a veces y se encuentra con esta pregunta sin querer evitar CLR. Esto me ayudó y podría ayudarlos.
John Fisher
Claro, estoy de acuerdo contigo @JohnFisher: es una respuesta útil para alguien que usa CLR. Pero en 2015, todavía nos gustaría una solución única de SQL en nuestro proyecto SQL (sin CLR) por varias razones, como lo hizo el OP en 2008. El año no importa :) Por ejemplo, la batería de su automóvil se lanzó en 1859 . Pero aún así desea evitar el uso de baterías más modernas, como las baterías de NiMH lanzadas más de 100 años después, por varias razones (como poder pagar un automóvil en absoluto :)
Ingeniero invertido
2
@DaveBoltman: Te perdiste la parte donde "La gente busca esto a veces y se encuentra con esta pregunta sin querer evitar CLR". Fue el punto clave.
John Fisher
claro, tienes razón @JohnFisher, dijiste eso. Me alegro de que te haya ayudado, y estoy seguro de que también ayudará a otros
Ingeniero invertido
2

Puede usar las características de expresión regular de VBScript usando la automatización OLE. Esto es mucho mejor que la sobrecarga de crear y mantener un ensamblaje. Asegúrese de pasar por la sección de comentarios para obtener una versión modificada mejor de la principal.

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;

Si obtiene un SQL Server blocked access to procedure 'sys.sp_OACreate'...error, use sp_reconfigurepara habilitar Ole Automation Procedures. (Sí, desafortunadamente, ¡eso es un cambio de nivel del servidor!)

Más información sobre el Testmétodo está disponible aquí

Codificación feliz

James Poulose
fuente
Sry, sé que esto es viejo, PERO: ¿Por qué VBScript a través de OLE es "mucho mejor" que CLR? Si SOLO piensa en el mantenimiento, PODRÍA estar en lo cierto, PERO ¿qué pasa con el rendimiento?
swe
1
@swe Por "mucho mejor", me refería al tiempo ahorrado debido a la sobrecarga de crear y mantener un ensamblado .NET solo para este propósito.
James Poulose