传递给LEFT或SUBSTRING函数的长度参数无效 - 为什么?

时间:2016-02-23 15:20:00

标签: sql tsql

我有这样的查询,有时我们得到了错误消息: 传递给LEFT或SUBSTRING函数的长度参数无效。

我不明白何时以及为何? 我可以看到执行计划在不同的数据库和不同的SQL服务器版本之间有所不同,我已经意识到不同的SQL服务器版本为运行查询的顺序做了不同的选择。

如果查询运行正常或是否有一个很好的解释,这只是运气吗?

DECLARE @param NVARCHAR(5) = (SELECT descriptionname FROM Table1 WHERE   
nameCode = 'SpecificCode')

SELECT        Table2.TableID
             ,SUBSTRING(Name,1,(CHARINDEX(':',Name,1))-1) AS Name
             ,SUBSTRING(Name
            ,(CHARINDEX(':',Name,1)+1)
            ,((CHARINDEX(':',Name,(CHARINDEX(':',Name,1)+1)))-(CHARINDEX(':',Name,1)+1))
                       ) AS Name2
FROM Table2 
INNER JOIN TypeTable
ON Table2.ttID = TypeTable.ttID
WHERE Code = 'Test'
AND Name LIKE '%:%'
AND  @param = 'True'

如果我们尝试下面的查询,它确实每次都有效。有什么重大的区别?

SELECT                Table2.TableID AS [Id]
                     ,SUBSTRING(Name,1,(CHARINDEX(':',Name,1))-1) AS Name
                     ,SUBSTRING(Name
                     ,(CHARINDEX(':',Name,1)+1)
         ,((CHARINDEX(':',Name,  
(CHARINDEX(':',Name,1)+1)))-(CHARINDEX(':',Name,1)+1))
                     ) AS Name2
FROM Table2 
INNER JOIN TypeTable
ON Table2.ttID = TypeTable.ttID
WHERE Code = 'Test'
AND Name LIKE '%:%'
AND  (SELECT descriptionname FROM Table1 WHERE nameCode = 'SpecificCode')  
= 'True'

1 个答案:

答案 0 :(得分:2)

面对像

这样非常脆弱的陈述
SUBSTRING(Name ,
       (CHARINDEX(':',Name,1)+1) ,
       ((CHARINDEX(':',Name,  
        (CHARINDEX(':',Name,1)+1)))-(CHARINDEX(':',Name,1)+1))
AS Name2

并且错误传递了无效的长度参数我不会从查看引擎开始。

相反,问题可能与数据有关。

查看documentation的长度参数

  

长度

     

是一个正整数或bigint表达式,指定了多少个   将返回表达式的字符。 如果长度为负,   生成错误并终止语句。如果总和   start和length大于in中的字符数   表达式,返回从start开始的整个值表达式。

我会查找会导致长度为负值的数据,并且我确定您会发现问题

e.g。

SELECT        
         Table2.TableID
         Name
FROM Table2 
INNER JOIN TypeTable
ON Table2.ttID = TypeTable.ttID
WHERE Code = 'Test'
AND Name LIKE '%:%'
AND  @param = 'True'
and (CHARINDEX(':',Name,1)+1)))-(CHARINDEX(':',Name,1)+1)) < 0

如果你已经淘汰了这个。那么是的,你确实拥有problem

中提到的@Damien_The_Unbelieve comment

最初我认为CTE可以做到这一点,但似乎优化器也可以在那里过度优化。所以达米恩further explains

  

我唯一依赖的是将查询拆分为两个不同的   查询并使用临时表或表变量进行存储   中间结果。

相关问题