使用Sql server case语句传递给substring函数的长度参数无效

Kub*_*uba 1 sql-server case

在case语句中使用它时,我遇到了substring函数的问题.

select              
case when -1<0 then 'ok' else SUBSTRING('abcd',1,-1) end
Run Code Online (Sandbox Code Playgroud)

给我一个问题:传递给substring函数的长度参数无效.

自第一个条件满足以来,为什么案件会"看"其他条件?

另一方面查询:

declare @a int;
set @a=-1

select              
@a,
case when @a<0 then 'ok' else SUBSTRING('abcd',1,@a) end
Run Code Online (Sandbox Code Playgroud)

提出正确答案'确定'没有任何错误.

Lar*_*rnu 8

问题是-1编译器在运行时为length参数解析了文字值.编译器知道它-1是无效的,因为length必须具有正值,因此在SQL运行之前标记错误.

在后一种语句中,传递的长度是一个变量.在编译时,变量具有"未知"值,因为它不是SET直到运行时,因此语法很好.

简单地说,编译器知道-1 for的长度SUBSTRING是无效的,无论SQL是否实际运行,以及错误.

与其他函数不同,例如STUFFREPLICATE,表示"如果length为负,则返回空字符串".,SUBSTRING,LEFT,和RIGHT所有的状态:"如果integer_expression为负,则返回一个错误." 对于文字值,似乎编译器正在检查这些值,即使它们永远不会被使用,然后标记错误.

这不仅限于CASE两者中的逻辑.例如,使用逻辑流运算符(如IF生成相同的行为):

IF 1 = 0
    SELECT LEFT('abc',-1)
Run Code Online (Sandbox Code Playgroud)

ISNULL功能一样:

SELECT ISNULL('ok',RIGHT('abc',-1));
Run Code Online (Sandbox Code Playgroud)

但是,它只与字面值一起出现.例如,如果您要使用列中的值,则不会出现以下行为:

IF 1 = 0 
    SELECT SUBSTRING('abc',1,n) FROM (VALUES(1),(-1)) V(n);
Run Code Online (Sandbox Code Playgroud)

这不会返回错误,即使所有内容VALUES都是文字.那是因为n尚未评估价值.