Sql server SQL Server 2008 R2-标量UDF导致无限循环
以下代码导致无限循环或执行速度非常慢:Sql server SQL Server 2008 R2-标量UDF导致无限循环,sql-server,sql-server-2008,tsql,pattern-matching,user-defined-functions,Sql Server,Sql Server 2008,Tsql,Pattern Matching,User Defined Functions,以下代码导致无限循环或执行速度非常慢: 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);
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的计算结果为空?在PATINDEX函数上,如果模式或表达式为NULL,PATINDEX将返回NULL,在这种情况下,NULL将导致无限循环
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
也被忽略了?)
的BOL条目没有明确说明如何在[]
中使用-
将其视为集合的一部分,但有以下示例
LIKE '[-acdf]'
为了匹配
-,a、c、d或f
,我假设它需要是集合中的第一项(即[^a-zA-Z0-9.~-]
需要更改为[^-a-zA-Z0-9.~~-]
)。这也与我上面的测试结果相匹配。看起来您可以通过在PATINDEX
中将@DirtyUriPart
转换为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);
您永远不会在循环中更改
@DirtyUriPart
,因此@i
的值在后续迭代中永远不会更改。不,这是我在恐慌和混乱我的代码。它仍然会导致无限循环。看起来可能需要将模式更改为%[^-a-zA-Z0-9.~\]%。我假设它将-
视为范围语法的一部分,即使它没有RHS。啊,啊,这太可怕了。这就是为什么我尽量避免我不懂的东西。谢谢你的帮助。RHS是什么意思?“右手边”。我找不到任何文档说明如何处理不带LHS和RHS的-
符号,但需要做一些测试来确认这一点。我将在IF子句中添加一个is NULL检查,以确保它在@I为NULL时中断。问题在于PATINDEX模式。你能给我一些提示吗?当你说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中的一个bug吗?@ChrisCannon-不确定RE:bug。我看不到varchar
与nvarchar
之间在行为上的差异,这在任何地方都有记录,而且绝对不是直觉上认为应该有任何差异。在SQL Server 2000和SQL Server 2012上复制。所以,如果它是一个bug,那么它就是一个长期未被发现的bug。@AaronBertrand-