sql - 当 udf 包含在 "WHERE...IN"子句中时出现奇怪的错误

标签 sql sql-server-2008 user-defined-functions

我有一个拆分字符串的函数(为了清楚起见,粘贴在最后)。
单独使用时,此功能按预期工作。
例子:

SELECT value
FROM dbo.mg_fn_Split('2#1','#')

退货
-- value --
--   2   --
--   1   --
-----------

但是当在“WHERE IN”子句中使用时,如本例所示(稍后将详细介绍 tableA):
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
    )

编辑:我已经设置了一个 fiddle 来展示这一点:
http://sqlfiddle.com/#!3/9f9ff/3

最佳答案

当您在内部查询中的数据如下时会发生这种情况。

选择值
FROM dbo.mg_fn_Split('#','#') --------------> 你会在这里得到错误。

选择值
FROM dbo.mg_fn_Split('2#1','#') -------------> 这里没有错误。

选择值
FROM dbo.mg_fn_Split('2','#') -----> 这里没有错误。

选择值
FROM 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'而不是''......希望这会有所帮助。

关于sql - 当 udf 包含在 "WHERE...IN"子句中时出现奇怪的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12480321/

相关文章:

sql - Oracle SQL 触发器插入/更新

pandas - 使用 ArrayType 列将 UDF 重写为 pandas udf

java - jdbc.SQLServerException : Login failed for user for any user 异常

c# - 从 C# 将大对象插入 SQL Server

excel - xl2010/xl2013 的 TEXTJOIN 符合条件

excel - #在 Excel 中使用自定义函数时出现值错误

mysql - 确定给定表中的 PK

sql - 将vba变量日期传递给sql语句

php - 如何防止 PHP 中的 SQL 注入(inject)?

sql - 连接 2 个表并过滤 Sql 查询