Tengo este pequeño CLR que hace una función RegEX en una cadena en columnas.
Cuando se ejecuta en SQL Server 2014 (12.0.2000) en Windows Server 2012R2, el proceso se bloquea con
Mensaje 0, Nivel 11, Estado 0, Línea 0 Se produjo un error grave en el comando actual. Los resultados, si los hay, deben descartarse.
y da un volcado de pila si lo hago
select count (*) from table where (CLRREGEX,'Regex')
pero cuando lo hago
select * from table where (CLRREGEX,'Regex')
devuelve las filas.
Funciona perfectamente en la misma compilación de SQL Server que se ejecuta en Windows 8.1.
¿Algunas ideas?
- Editar Es tan simple como puede ser
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlTypes; //SqlString, SqlInt32, SqlBoolean
using System.Text.RegularExpressions; //Match, Regex
using Microsoft.SqlServer.Server; //SqlFunctionAttribute
public partial class UserDefinedFunctions
{
public static readonly RegexOptions Options = RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline;
[SqlFunction]
[Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = true)]
public static SqlBoolean RegExMatch(SqlString input, SqlString pattern)
{
if (input.IsNull || pattern.IsNull) //nulls dont qualify for a match
return SqlBoolean.False;
return Regex.IsMatch(input.Value, pattern.Value, RegexOptions.IgnoreCase);
}
}
Entonces, con pequeños cambios, esto funciona ahora: la lección principal en C # parece ser la misma que en TSQL, tenga cuidado con la conversión de datos implícita.
using System;
using System.Text;
using System.Data.SqlTypes; //SqlString, SqlInt32, SqlBoolean
using System.Text.RegularExpressions; //Match, Regex
using Microsoft.SqlServer.Server; //SqlFunctionAttribute
public partial class UserDefinedFunctions
{
public static readonly RegexOptions Options = RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant;
[Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = true, DataAccess = DataAccessKind.Read)]
public static SqlBoolean RegExMatch(SqlString input, SqlString pattern)
{
if (input.IsNull || pattern.IsNull) //nulls dont qualify for a match
return SqlBoolean.False;
string sqldata = input.ToString();
string regex = pattern.ToString();
return Regex.IsMatch(sqldata, regex);
}
[SqlFunction]
atributo duplicado . ¿Es ese el código exacto? No creo que eso compile. La distinción de Framework versión 2.0 / 3.0 / 3.5 no es un problema ya que está utilizando 4.0 / 4.5 / 4.5.x / etc o lo que sea que esté en ese servidor ya que está en SQL Server 2014, que está vinculado a CLR versión 4. Es el servidor que muestra el problema de 32 bits? ¿Cuánta memoria tiene en comparación con los otros servidores? ¿Y ha verificado los registros de SQL Server justo después de recibir ese error?
MatchTimeout
propiedad. Pero tampoco creo que ese sea realmente el problema si solo está pasando 5 caracteres como máximo. Que es posible que éste equipo dispone de una instalación corrupta de .NET Framework, y que puede ser reparada una vez trucha actividades pesqueras han dejado ;-). Además, [0-9].*
es simple pero también ineficiente, ya que coincide con todos los caracteres, si los hay, después del primer dígito; usar solo [0-9]
para un IsMatch
es mejor.
DataAccessKind
a Read
? Eso solo lo ralentiza y no está haciendo ningún acceso a datos. Además, me doy cuenta de que parece estar funcionando ahora, pero sería cauteloso con el uso del ToString()
método en lugar de la Value
propiedad, ya que no creo que ToString maneje las codificaciones correctamente, o algo así. ¿Para qué está configurada la recopilación de sus bases de datos? Por supuesto, acabo de volver a leer uno de sus comentarios anteriores y veo que la columna es VARCHAR en lugar de NVARCHAR. ¿Ese campo tiene una clasificación diferente a la de la base de datos?
SqlFunction
método está marcado comoIsDeterministic=true
? ¿El conjunto está marcado comoSAFE
?