Mam ten mały CLR, który wykonuje funkcję RegEX na ciąg znaków w kolumnach.
Podczas uruchamiania w programie SQL Server 2014 (12.0.2000) w systemie Windows Server 2012R2 proces ulega awarii
Wiadomość 0, poziom 11, stan 0, wiersz 0 Wystąpił poważny błąd w bieżącym poleceniu. Ewentualne wyniki należy odrzucić.
i daje zrzut stosu, jeśli to zrobię
select count (*) from table where (CLRREGEX,'Regex')
ale kiedy robię
select * from table where (CLRREGEX,'Regex')
zwraca wiersze.
Działa doskonale na tej samej kompilacji SQL Server działającej w systemie Windows 8.1.
Jakieś pomysły?
- Edycja To jest tak proste, jak to tylko możliwe
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);
}
}
Tak więc po drobnych zmianach działa to teraz: główna lekcja w języku C # wydaje się być taka sama jak w TSQL, strzeż się niejawnej konwersji danych.
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]
atrybutu. Czy to dokładnie kod? Nie sądzę, żeby to się skompilowało. Rozróżnienie Framework w wersji 2.0 / 3.0 / 3.5 nie stanowi problemu, ponieważ używasz wersji 4.0 / 4.5 / 4.5.x / etc lub cokolwiek, co znajduje się na tym serwerze, ponieważ korzystasz z SQL Server 2014, który jest powiązany z wersją 4. CLR serwer pokazuje problem w wersji 32-bitowej? Ile pamięci ma w porównaniu do innych serwerów? I czy sprawdziłeś dzienniki SQL Server zaraz po otrzymaniu tego błędu?
MatchTimeout
właściwości. Ale nie sądzę, że to jest tak naprawdę problem, jeśli podajesz maksymalnie 5 znaków. To jest możliwe, że jedna maszyna ma uszkodzone zainstalować .NET Framework, i które mogą być naprawione raz pstrąg działalność połowowa przestały ;-). Ponadto [0-9].*
jest prosty, ale również nieefektywny, ponieważ pasuje do wszystkich znaków, jeśli występują, po pierwszej cyfrze; używanie tylko [0-9]
dla IsMatch
jest lepsze.
DataAccessKind
na Read
? To tylko spowalnia i nie masz dostępu do danych. Zdaję sobie również sprawę, że wydaje się, że teraz działa, ale byłbym ostrożny z użyciem tej ToString()
metody Value
zamiast właściwości, ponieważ nie sądzę, aby ToString poprawnie obsługiwał kodowanie lub coś w tym rodzaju. Jakie jest ustawienie sortowania baz danych? Oczywiście, po prostu ponownie przeczytałem jeden z twoich komentarzy powyżej i widzę, że kolumna to VARCHAR zamiast NVARCHAR. Czy to pole ma inne zestawienie niż baza danych?
SqlFunction
metoda jest oznaczona jakoIsDeterministic=true
? Czy zespół jest oznaczony jakoSAFE
?