选择()不按预期工作

Har*_* CO 7 sql sql-server-2012

当我结合随机整数生成时,CHOOSE()我得到了意想不到的NULL值.

以下应该只返回字母a- e而是NULL也包含在值中:

查询:

;WITH cte AS (SELECT 1 RN
              UNION  ALL 
              SELECT RN + 1 
              FROM cte
              WHERE RN < 100)
SELECT DISTINCT CHOOSE(1 + ABS(CRYPT_GEN_RANDOM(8)%5),'a','b','c','d','e','f')
FROM cte
Run Code Online (Sandbox Code Playgroud)

结果:

NULL
a
b
c
d
e
Run Code Online (Sandbox Code Playgroud)

预期成绩:

a
b
c
d
e
Run Code Online (Sandbox Code Playgroud)

随机数生成按预期工作,仅返回值1-5:

;WITH cte AS (SELECT 1 RN
              UNION  ALL 
              SELECT RN + 1 
              FROM cte
              WHERE RN < 50)
SELECT 1 + ABS(CRYPT_GEN_RANDOM(8)%5)
FROM cte
Run Code Online (Sandbox Code Playgroud)

演示:SQL小提琴

CHOOSE() 如下工作(索引从1开始):

SELECT CHOOSE(3,'dog','cat','horse','fish')  
-- horse
SELECT CHOOSE(8,'dog','cat','horse','fish')  
-- NULL
Run Code Online (Sandbox Code Playgroud)

在功能使用随机数生成工作正常LEFT(),RIGHT(),CHAR(),等.一个解决方法会很好,但大多数时候我很好奇为什么我会得到NULL价值观.

Gor*_*off 1

这很奇怪,可能属于错误类别。当然,您所做的事情很奇怪,因为您将随机的位模式视为数字。应该是有效的,但可能会产生意想不到的后果。而且,这不是溢出问题。它与 的其他值一起发生8

见证以下内容(在SQL Fiddle上):

WITH cte AS (SELECT 1 RN
              UNION  ALL 
              SELECT RN + 1 
              FROM cte
              WHERE RN < 100)
SELECT  CHOOSE(1 + ABS(n),'a','b','c','d','e','f'),
        CHOOSE(1 + abs(CRYPT_GEN_RANDOM(8)%5),'a','b','c','d','e','f')
FROM (select abs(CRYPT_GEN_RANDOM(8)%5) as n
      from cte
     ) n
order by 1
Run Code Online (Sandbox Code Playgroud)

第一列是never NULL。第二列是周期性的NULL。换句话说,如果将值分配给另一个变量,则会产生影响。我可以想象某种 8 字节大整数模式代表 NaN,但这种情况并不会发生太多。

鉴于它在直接调用时失败,但在存在中间变量时有效,我得出的结论是这可能是某种错误。我想知道是否有记录在某处。

  • 不是错误。CHOOSE 扩展为 CASE 表达式,并且在 CASE 表达式内,针对每个潜在输出重新评估 CRYPT_GEN_RANDOM。显然,有时第一次评估会产生 2,而接下来的 5 次评估会产生 1,从而将您推向 ELSE 领域。[Paul 在这里用 CHECKSUM(NEWID()) 演示了这一点,但概念是相同的](http://stackoverflow.com/questions/21918536/how-does-this-case-expression-reach-the-else-clause /21918828#21918828)。 (9认同)
  • 而 `arg1` 是在每种情况下对函数的不同评估 (3认同)
  • 我不认为“实施是故意破坏的”。我认为几年前就做出了设计决定,但你只是不喜欢这个决定。:-) `CHOOSE()` 不提供任何新功能,而且 `COALESCE()` 也不提供任何新功能。它们都只是依赖于现有的“CASE”*表达式*行为。 (3认同)
  • @亚伦伯特兰。。。这两个函数会带来不必要的问题。我猜 ANSI 对于 `coalesce()` 中的多次求值没有什么可说的,但是当 `isnull()` 按预期工作时(但仅在两个参数上),出现这种行为似乎很奇怪。顺便说一句,我在这里很想念你。 (2认同)