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:错误。我看不出 varcharnvarchar 之间的行为差​​异记录在任何地方,而且绝对不直观,应该有任何差异。 在 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 server2008 r2 ISO文件

windows 2012 r2怎么安装sql server 2008 r2

跪求SQL Server 2008 R2 Standard (64

安装SQL Server 2008 R2 时提示“服务器没有及时响应或控制请求”怎么解决?

SQL Server2008和SQL Server2008R2的区别,高手速进