Sql server SQL';s选择是选择错误的结果(并产生“严重”错误)

Sql server SQL';s选择是选择错误的结果(并产生“严重”错误),sql-server,tsql,Sql Server,Tsql,有趣的是,我总是可以通过以下方式触发“严重”错误: WITH SillySequence (Ordinal) AS ( SELECT 1 UNION ALL SELECT (1 + Ordinal) FROM SillySequence WHERE Ordinal < 100 ) SELECT SometimesNull = CHOOSE( 5 + ABS(CHECKSUM(NEWID()) % 2),

有趣的是,我总是可以通过以下方式触发“严重”错误:

WITH SillySequence (Ordinal) AS (
    SELECT 1
    UNION ALL
    SELECT (1 + Ordinal) FROM SillySequence WHERE Ordinal < 100
)
SELECT
    SometimesNull =
        CHOOSE(
            5 + ABS(CHECKSUM(NEWID()) % 2),
            1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
FROM SillySequence
消息0,11级,状态0,第20行

无法继续执行,因为会话处于终止状态

消息0,级别20,状态0,第20行

当前命令发生严重错误。如果有结果,则应放弃


我已经在SQL Server 2016中使用兼容性级别
110
120
130

测试了上述示例。您误解了
choose()
的工作原理。在我看来,这是因为你是一个聪明的人,期望软件以合理的方式工作

choose(x,a,b)
的定义相当于:

SELECT CHOOSE(
    (SELECT 1 + ABS(CHECKSUM(NEWID()) % 2)),
    'one', 'two')
x
是一个常数时,这就足够简单了。当
x
引用一列时(如您的“永不为空”示例中所示),就足够简单了。当
x
是非易失性表达式时,就足够简单了。当
x
是一个不确定的表达式时,99.9%是违反直觉的(有些人可能会有不同的想法和评论;)

这是什么意思?好吧,你正在执行:

(case when x = 1 then a
      when x = 2 then b
 end)
也就是说,表达式有两个随机数。事实上,每个可能的目标都有一个随机数(我说的是“反直觉”,不是吗?)


好吧,大约25%的时候,两种比较都会失败。并且,结果将是
NULL
。我记得我第一次学习时花了很多时间调试代码。

NEWID()计算了10次。案例和选择在这里是相似的;请看。如果我没记错的话,
COALESCE()
会遇到类似的问题,因为它会被重写为一个
大小写
表达式。特别令人困惑,因为
ISNULL()
不是那样工作的。谢谢你的回答!“严重错误”仍然是个谜,但这解释了最初的行为(否则无法解释)。
(case when x = 1 then a
      when x = 2 then b
 end)
(case when 1 + ABS(CHECKSUM(NEWID()) % 2) = 1 then a
      when 1 + ABS(CHECKSUM(NEWID()) % 2) = 2 then b
 end)