1

以下代码导致无限循环或执行速度非常慢:

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' 导致无限循环
  • 等等

请帮忙!

4

3 回答 3

2
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被忽略?)

LIKE的 BOL 条目没有明确讨论如何使用-within[]将其视为集合的一部分,但确实有示例

LIKE '[-acdf]'

匹配-, a, c, d, or f所以我假设它需要是一组中的第一项(即[^a-zA-Z0-9.~_-]需要更改为[^-a-zA-Z0-9.~_])。这也符合我上面的测试结果。

于 2012-05-20T20:39:42.903 回答
1

@DirtyUriPart 是否有可能评估为 NULL?在 PATINDEX 函数上,如果模式或表达式为 NULL,则 PATINDEX 返回 NULL,在这种情况下,NULL 将导致无限循环

于 2012-05-20T20:13:18.093 回答
0

看起来您可以通过转换@DirtyUriPartVARCHAR(200)in来解决问题PATINDEX,这将导致破折号与类中的其他字符一起被识别:

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);
于 2012-05-20T21:16:21.980 回答