Spö*_*rri 12 sql-server sql-clr sql-server-2014
我有这个小型 CLR,它对列中的字符串执行 RegEX 函数。
在 Windows Server 2012R2 上的 SQL Server 2014 (12.0.2000) 上运行时,进程崩溃
Msg 0, Level 11, State 0, Line 0 当前命令发生严重错误。结果,如果有的话,应该被丢弃。
如果我这样做,并给出堆栈转储
select count (*) from table where (CLRREGEX,'Regex')
Run Code Online (Sandbox Code Playgroud)
但是当我这样做的时候
select * from table where (CLRREGEX,'Regex')
Run Code Online (Sandbox Code Playgroud)
它返回行。
在 Windows 8.1 上运行的相同 SQL Server 版本上完美运行。
有任何想法吗?
-- 编辑就这么简单
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);
}
}
Run Code Online (Sandbox Code Playgroud)
因此,现在可以通过一些小的更改来实现:C# 中的主要课程似乎与 TSQL 中的相同,请注意隐式数据转换。
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);
}
Run Code Online (Sandbox Code Playgroud)
该问题是 Windows 操作系统和 SQL Server(特别是加载程序集的数据库)之间的区域设置冲突。您可以运行以下查询来查看它们的设置:
SELECT os_language_version,
DATABASEPROPERTYEX(N'{name of DB where Assembly exists}', 'LCID') AS 'DatabaseLCID'
FROM sys.dm_os_windows_info;
Run Code Online (Sandbox Code Playgroud)
如果它们不同,那么您肯定会得到一些“奇怪”的行为,例如您所看到的。问题在于:
SqlString
不仅仅包括文本本身:它还包括程序集所在数据库的默认排序规则。排序规则由两条信息组成:区域设置信息(即 LCID)和比较选项(即 SqlCompareOptions),后者详细说明了对大小写、重音、假名、宽度或所有内容(二进制和二进制 2)的敏感性。.Value
当引用 SqlString 参数而不使用或.ToString()
使其隐式转换为 时,通常会发生冲突SqlString
。在这种情况下,会导致异常,指出 LCID 不匹配。
显然还有其他场景,例如执行(部分/全部?)字符串比较,包括使用正则表达式时,如本例所示(尽管到目前为止我还无法重现这一点)。
一些修复的想法:
理想(关于比较如何进行的期望将始终得到满足):
不太理想(Windows 区域设置的行为可能与相等和排序的规则不同,因此可能会出现意外结果):
.ToString
方法或.Value
属性,它们都返回不带 SQL Server LCID 的字符串,因此所有操作都将使用操作系统 LCID。可能有帮助:
SqlChars
而不是SqlString
因为它不会带来来自 SQL Server 的 LCID 和排序规则信息StringComparison.InvariantCulture
:
String.Compare(string, string, StringComparison.InvariantCulture)
或者String.Compare(string, string, StringComparison.InvariantCultureIgnoreCase)
RegexOptions.CultureInvariant
归档时间: |
|
查看次数: |
1268 次 |
最近记录: |