SQL Server 2008 R2 - 标量 UDF 导致无限循环
Posted
技术标签:
【中文标题】SQL Server 2008 R2 - 标量 UDF 导致无限循环【英文标题】:SQL Server 2008 R2 - Scalar UDF results in infinite loop 【发布时间】:2012-05-20 19:44:45 【问题描述】:以下代码会导致无限循环或执行速度非常慢:
CREATE FUNCTION [dbo].[CleanUriPart]
(
-- Add the parameters for the function here
@DirtyUriPart nvarchar(200)
)
RETURNS nvarchar(200)
AS
BEGIN;
-- Declare the return variable here
DECLARE @Result nvarchar(200);
DECLARE @i int;
SET @i = 1;
WHILE 1 = 1
BEGIN;
SET @i = PATINDEX('%[^a-zA-Z0-9.~_-]%', @DirtyUriPart COLLATE Latin1_General_BIN);
IF @i > 0
SET @DirtyUriPart = STUFF(@DirtyUriPart, @i, 1, '-');
ELSE
BREAK;
END;
-- Add the T-SQL statements to compute the return value here
SELECT @Result = @DirtyUriPart;
-- Return the result of the function
RETURN @Result;
END;
输入/输出应如下:
'abcdef' -> 'abcdef' 工作正常 'abc-def' -> 'abc-def' 导致无限循环 'abc*def' -> 'abc-def' 导致无限循环 等请帮忙!
【问题讨论】:
您永远不会在循环内更改@DirtyUriPart
,因此@i
的值在后续迭代中永远不会改变。
不,那是我惊慌失措并弄乱我的代码。它仍然会导致无限循环。
看起来模式实际上可能需要更改为'%[^-a-zA-Z0-9.~_]%'
。我假设它将 -
视为范围语法的一部分,即使它没有 RHS。
啊啊啊啊太吓人了。这就是为什么我尽量避免我不理解的东西。谢谢你的帮助。 RHS 是什么意思?
“右手边”。我找不到任何说明如何处理没有 LHS 和 RHS 的 -
符号的文档,因此需要进行一些测试以确认这一点。
【参考方案1】:
SELECT PATINDEX('%[^a-]%', N'aaa-def' COLLATE Latin1_General_BIN),
PATINDEX('%[^-a]%', N'aaa-def' COLLATE Latin1_General_BIN),
PATINDEX('%[^a-]%', 'aaa-def' COLLATE Latin1_General_BIN),
PATINDEX('%[^-a]%', 'aaa-def' COLLATE Latin1_General_BIN)
返回
----------- ----------- ----------- -----------
1 5 5 5
因此,对于varchar
数据类型,尾随-
似乎被视为集合的一部分,而对于nvarchar
,它被忽略(视为格式错误的范围,因为a
也被忽略?) p>
LIKE 的 BOL 条目没有明确说明如何在 []
中使用 -
以使其被视为集合的一部分,但确实有示例
LIKE '[-acdf]'
为了匹配-, a, c, d, or f
,所以我假设它需要成为集合中的第一项(即[^a-zA-Z0-9.~_-]
需要更改为[^-a-zA-Z0-9.~_]
)。这也符合我上面的测试结果。
【讨论】:
当您说SELECT PATINDEX('%[^a-zA-Z0-9.~_-]%', N'abc-def' COLLATE Latin1_General_BIN), PATINDEX('%[^-a-zA-Z0-9.~_]%', N'abc-def' COLLATE Latin1_General_BIN)
返回不同的结果时,您让我担心!他们确实返回了不同的结果,一个正确一个不正确......所以是的%[^-a-zA-Z0-9.~_]%'
似乎工作正常。再次感谢 - 我在星期天学到了很多东西!
那么这是 SQL Server 2008 中的错误吗?
@ChrisCannon - 不确定 RE:错误。我看不出 varchar
与 nvarchar
之间的行为差异记录在任何地方,而且绝对不直观,应该有任何差异。
在 SQL Server 2000 和 SQL Server 2012 上重现。因此,如果它是一个错误,那么它就是一个已经逃脱检测很长时间的错误。
@AaronBertrand - Response to my Connect Item【参考方案2】:
@DirtyUriPart 是否有可能评估为 NULL?在 PATINDEX 函数上,如果模式或表达式中的任何一个为 NULL,则 PATINDEX 返回 NULL,在这种情况下为 NULL 将导致无限循环
【讨论】:
我将在 IF 子句中添加对 IS NULL 的检查,以确保它在 @i IS NULL 的位置中断。问题在于 PATINDEX 模式。你能给我一些建议吗?【参考方案3】:看起来您可以通过将@DirtyUriPart
转换为PATINDEX
中的VARCHAR(200)
来解决此问题,这将导致破折号与类中的其他字符一起被识别:
DECLARE @DirtyUriPart nvarchar(200)='abc-def';
-- Returns 0
SELECT PATINDEX('%[^a-zA-Z0-9.~_-]%', CAST(@DirtyUriPart AS VARCHAR(200)) COLLATE Latin1_General_BIN);
-- Returns 4
SELECT PATINDEX('%[^a-zA-Z0-9.~_-]%', @DirtyUriPart COLLATE Latin1_General_BIN);
【讨论】:
以上是关于SQL Server 2008 R2 - 标量 UDF 导致无限循环的主要内容,如果未能解决你的问题,请参考以下文章
配置好了raid1,安装windows server 2008r2。
windows 2012 r2怎么安装sql server 2008 r2
跪求SQL Server 2008 R2 Standard (64