CASE语句中的空值


8

在学习70-461考试时,我正在玩SSMS中的一些东西,以学到更多知识,并且遇到了一些麻烦。我正在尝试创建一个表以供使用,因此我不必更改/删除AdventureWorks或TSQL2012数据库中任何已创建的表。在实际创建要使用的表之前,我已经创建了一个临时表来测试我的代码,这是我用来在表中插入值的代码:

DECLARE @i INT = 1
 WHILE @i < 10
    BEGIN
    INSERT INTO #TestEmployeeCountry 
    VALUES ( SUBSTRING('ABCDEFGHIJKLMNOP', @i, 1), 
        CASE (SELECT ABS(CHECKSUM(NEWID()))%10 +1)
            WHEN 1 THEN 'USA'
            WHEN 2 THEN 'CANADA'
            WHEN 3 THEN 'MEXICO'
            WHEN 4 THEN 'UK'
            WHEN 5 THEN 'FRANCE'
            WHEN 6 THEN 'SPAIN'
            WHEN 7 THEN 'RUSSIA'
            WHEN 8 THEN 'CHINA'
            WHEN 9 THEN 'JAPAN'
            WHEN 10 THEN 'INDIA'
        END)
    SET @i = @i + 1
    END;

我遇到的问题是我不断收到一条错误消息:“无法将值NULL插入表'tempdb.dbo。#TestEmployeeCountry的'Country'列中”这是因为我将Country列设置为NOT NULL,并且我的代码确实适用于某些插入,问题是我从case语句中随机获取了NULL值。

我知道要解决此问题,我可以轻松添加另一行“ DEFAULT xxxxxx”,但是我想了解发生了什么,因为基于我所看到的,我不必这样做,对吗?我以为我正确地写了case语句,只给我一个1-10之间的数字,而仅测试了1000次尝试中的特定select语句,我总是得到一个介于1-10之间的随机数,没有更大或更小的值。谁能帮助我了解为什么此代码尝试在该列中输入NULL值?

Answers:


8

为什么这样的情况已经被@PaulWhite在SO问题中得到了回答:这个CASE表达式如何到达ELSE子句?

要解决该问题,您应该ABS(CHECKSUM(NEWID()))%10 +1INSERT语句之前/之前计算outside / out,因此它只能计算一次。就像是:

DECLARE @i INT = 1 ;
DECLARE @rand INT ;
 WHILE @i <= 10
   BEGIN
    SET @rand = ABS(CHECKSUM(NEWID()))%10 +1 ;
    INSERT INTO TestEmployeeCountry 
    VALUES ( SUBSTRING('ABCDEFGHIJKLMNOP', @i, 1), 
        CASE @rand
            WHEN 1 THEN 'USA'
            WHEN 2 THEN 'CANADA'
            WHEN 3 THEN 'MEXICO'
            WHEN 4 THEN 'UK'
            WHEN 5 THEN 'FRANCE'
            WHEN 6 THEN 'SPAIN'
            WHEN 7 THEN 'RUSSIA'
            WHEN 8 THEN 'CHINA'
            WHEN 9 THEN 'JAPAN'
            WHEN 10 THEN 'INDIA'
        END) ;
    SET @i = @i + 1 ;
   END ;

另请注意,在您的代码中,这10个国家/地区不会以相同的概率放置在表格中!第一个国家(USA)将有10%的机会,第二个国家将具有9%((100%-10%)*10%),第三个国家(8.1 (100%-19%)*10%),(),依此类推。这样的机会很小(大约1/e),以至于10个都不被选中,CASE表达式转到默认值ELSE NULL,您会收到错误消息。(如果您在列中允许使用null并运行SQLfiddle脚本,则可以检查概率。)

根据上述内容,另一种解决方法是更改​​表达式以符合SQL-Server执行的方式,CASE并且所有10种情况具有相同的概率:

    CASE 0
        WHEN ABS(CHECKSUM(NEWID()))%10 THEN 'USA'
        WHEN ABS(CHECKSUM(NEWID()))%9 THEN 'CANADA'
        WHEN ABS(CHECKSUM(NEWID()))%8 THEN 'MEXICO'
        WHEN ABS(CHECKSUM(NEWID()))%7 THEN 'UK'
        WHEN ABS(CHECKSUM(NEWID()))%6 THEN 'FRANCE'
        WHEN ABS(CHECKSUM(NEWID()))%5 THEN 'SPAIN'
        WHEN ABS(CHECKSUM(NEWID()))%4 THEN 'RUSSIA'
        WHEN ABS(CHECKSUM(NEWID()))%3 THEN 'CHINA'
        WHEN ABS(CHECKSUM(NEWID()))%2 THEN 'JAPAN'
        ELSE 'INDIA'
    END
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.