Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 当包含在“WHERE…in”子句中时,udf中出现奇怪的错误_Sql_Sql Server 2008_User Defined Functions - Fatal编程技术网

Sql 当包含在“WHERE…in”子句中时,udf中出现奇怪的错误

Sql 当包含在“WHERE…in”子句中时,udf中出现奇怪的错误,sql,sql-server-2008,user-defined-functions,Sql,Sql Server 2008,User Defined Functions,我有一个函数,它可以拆分粘贴在末尾的字符串,以清晰显示。 单独使用时,此功能可以正常工作。 例如: 返回 -- value -- -- 2 -- -- 1 -- ----------- 但当在WHERE in子句中使用时,如本例所示,请稍后在表a中详细说明: SELECT * FROM TableA WHERE TableA.id IN ( SELECT value FROM dbo.mg_fn_Split('2#1','#') ) 我得到一个错误:传递给LEFT或S

我有一个函数,它可以拆分粘贴在末尾的字符串,以清晰显示。 单独使用时,此功能可以正常工作。 例如:

返回

-- value --
--   2   --
--   1   --
-----------
但当在WHERE in子句中使用时,如本例所示,请稍后在表a中详细说明:

SELECT * FROM TableA WHERE TableA.id IN
(
  SELECT value
  FROM dbo.mg_fn_Split('2#1','#')
)
我得到一个错误:传递给LEFT或SUBSTRING函数的长度参数无效

这里以表A为例。使用不同的表(假设它们具有id列)有时会返回正确的结果,而在其他表上则会出现错误

我假设它与执行顺序有关,但我仍然看不出什么会破坏函数

我在寻找一个关于发生了什么的解释,而不是用这个来代替。我知道我可以使用连接来获得结果

函数定义:

-- Description: Returns a table containing the results of a string-split operation.
-- Params:
--      DelimitedList: The string to split
--      Delimiter: The delimiter char, defaults to ','
-- Columns:
--      Position - The char index of the item
--      Value - The actual item
-- =============================================
CREATE Function [dbo].[mg_fn_Split]
(   
    @DelimitedList nvarchar(max)
    , @Delimiter nvarchar(2) = ','
)
RETURNS TABLE 
AS
RETURN 
    (
    With CorrectedList As
        (
        Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
            + @DelimitedList
            + Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
            As List
            , Len(@Delimiter) As DelimiterLen
        )
        , Numbers As 
        (
        Select TOP( Coalesce(DataLength(@DelimitedList)/2,0) ) Row_Number() Over ( Order By c1.object_id ) As Value
        From sys.columns As c1
            Cross Join sys.columns As c2
        )
    Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position
        , Substring (
                    CL.List
                    , CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen     
                    , CharIndex(@Delimiter, CL.list, N.Value + 1)                           
                        - ( CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen ) 
                    ) As Value
    From CorrectedList As CL
        Cross Join Numbers As N
    Where N.Value <= DataLength(CL.List) / 2
        And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter
    )
编辑:我准备了一把小提琴来展示:

当您将内部查询中的数据变为以下内容时,就会发生这种情况

选择值 从dbo.mg\u fn\u Split,---->您将在这里得到错误

选择值 从dbo.mg_fn_Split'21',--->这里没有错误

选择值 从dbo.mg_fn_Split'2',------------->这里没有错误

选择值 从dbo.mg_fn_Split,-------------->这里没有错误

因此,基本上,当要拆分的数据和分隔符相同时,就会发生错误

问题在于这些陈述

      " Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
        + @DelimitedList
        + Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End"
如果你把这个改成

    Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '1' End
        + @DelimitedList
        + Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '1' End

那就好了。。您所做的只是添加“1”而不是。。。希望这有帮助

内联UDF被扩展到查询中,因此可能某些联接操作或筛选器的计算顺序与您预期的不同。不使用联接的原因是什么?如果可能的话,最好不要在sql命令中使用字符串解析。我同意Martin的评论,我相信函数的WHERE子句被推到了Select*from表中。如果您在函数中注释掉以下内容和SubstringCL.List,N.Value,CL.DelimiterLen=@Delimiter,您将得到由其中一个子字符串值计算为-1引起的相同问题。同意Martin的注释。你可以很容易地解决这个问题。在主查询中,在SELECT子句的子字符串的第三个参数中,将NULLIF应用于minuend:NULLIFCharIndex@Delimiter,CL.list,N.Value+1,0-…正如我在文章中提到的,函数的参数没有改变。我做了一个编辑,添加了一把小提琴,请参阅以获取问题的演示。
    Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '1' End
        + @DelimitedList
        + Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '1' End