sql-server – CASE构造的奇怪行为

前端之家收集整理的这篇文章主要介绍了sql-server – CASE构造的奇怪行为前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
背景:我试图在创建虚拟数据时获得一些随机的“十六进制”值,并提出了这种结构:
SELECT TOP 100 
   result = (CASE ABS(Binary_Checksum(NewID())) % 16 
                WHEN -1 THEN 'hello'
                WHEN 0 THEN '0' 
                WHEN 1 THEN '1' 
                WHEN 2 THEN '2' 
                WHEN 3 THEN '3'
                WHEN 4 THEN '4' 
                WHEN 5 THEN '5' 
                WHEN 6 THEN '6' 
                WHEN 7 THEN '7'
                WHEN 8 THEN '8' 
                WHEN 9 THEN '9' 
                WHEN 10 THEN 'a' 
                WHEN 11 THEN 'b'
                WHEN 12 THEN 'c' 
                WHEN 13 THEN 'd' 
                WHEN 14 THEN 'e' 
                WHEN 15 THEN 'f' 
                ELSE 'huh'  END)
          FROM sys.objects

在我的sql Server 2008 R2实例上运行时,我得到了很多’呵呵’的记录:

result
------
huh
3
huh
huh
6
8
6

我真的不明白为什么.
我期望发生的是:

>对于每条记录,NewID()都会出现一个新的随机
> Binary_Checksum()根据所述值计算int
> ABS()使价值为正
>%16如果除以16则返回该正值的余数,然后该值将是0到15之间的值
> CASE构造将值转换为相关字符
>由于0到15之间的每个值都有WHEN,因此永远不需要ELSE

或者至少,这就是我认为应该发生的事情……但显然在路上出了问题……

当用两步法(通过临时表)做同样的事情时,哼哼……

SELECT TOP 100 x = ABS(Binary_Checksum(NewID())) % 16,result = 'hello'
  INTO #test
  FROM sys.objects

UPDATE #test 
   SET result = (CASE x WHEN 0 THEN '0' WHEN 1 THEN '1' WHEN 2 THEN '2' WHEN 3 THEN '3'
                        WHEN 4 THEN '4' WHEN 5 THEN '5' WHEN 6 THEN '6' WHEN 7 THEN '7'
                        WHEN 8 THEN '8' WHEN 9 THEN '9' WHEN 10 THEN 'a' WHEN 11 THEN 'b'
                        WHEN 12 THEN 'c' WHEN 13 THEN 'd' WHEN 14 THEN 'e' WHEN 15 THEN 'f' 
                        ELSE 'huh'  END)

SELECT * FROM #test

有谁理解这个?据我所知它应该给出相同的结果(它确实是复制粘贴),无论我直接或通过临时表执行…但是如果我在一个语句中执行它,显然会出现问题.

PS:我不需要为此修复,我已经有一个解决方法(见下文),我只是希望有人可以解释我为什么这样做.

解决方法

SELECT TOP 100 result = SubString('0123456789abcdef',1 + (ABS(Binary_Checksum(NewID())) % 16),1) 
  FROM sys.objects

解决方法

我相信,与 simple CASE expression的描述相反,它实际上为每个input_expression = when_expression比较重新评估input_expression(这通常是安全的,除非在这种情况下,在input_expression中有一个非确定性函数)

所以,会发生的事情是,每次比较时它会在0到15之间产生不同的随机数,如果在16次评估/比较之后,它从未生成匹配的数字,那么就会出现问题.

这不会产生什么:

SELECT TOP 100 
    result = (CASE ABS(Binary_Checksum(Value)) % 16 
            WHEN -1 THEN 'hello'
            WHEN 0 THEN '0' 
            WHEN 1 THEN '1' 
            WHEN 2 THEN '2' 
            WHEN 3 THEN '3'
            WHEN 4 THEN '4' 
            WHEN 5 THEN '5' 
            WHEN 6 THEN '6' 
            WHEN 7 THEN '7'
            WHEN 8 THEN '8' 
            WHEN 9 THEN '9' 
            WHEN 10 THEN 'a' 
            WHEN 11 THEN 'b'
            WHEN 12 THEN 'c' 
            WHEN 13 THEN 'd' 
            WHEN 14 THEN 'e' 
            WHEN 15 THEN 'f' 
            ELSE 'huh'  END)
          FROM (select NewID() as Value,* from sys.objects ) so

猜你在找的MsSQL相关文章