【问题标题】:Case Statement Syntax - SQL Server案例语句语法 - SQL Server
【发布时间】:2014-06-19 04:25:05
【问题描述】:

我正在尝试使用 SQL Server 2012 将一个非常简单的检查集成到触发器中。在 INSTEAD OF 触发器期间,我想根据此伪代码检查以下内容:

IF Inserted.FloorRef = ('various', 'different', 'strings')
THEN check that Inserted.FloorNumber IS NOT NULL

我声明了一个位变量,如果此测试通过或满足 else 条件,则该变量设置为 1,以便可以在已知条件下运行进一步的代码。我的代码在下面,但它失败了: 关键字“CASE”附近的语法不正确(Inserted.FloorRef) 并且; 必须声明标量变量“@Passed”

一定有一个或十个语法错误,但我找不到哪里错了?

DECLARE @Passed BIT = 0

CASE Inserted.FloorRef 
    WHEN EXISTS IN ('Floor', 'Level', 'Fl', 'L') THEN --FloorNumber is required
        CASE Inserted.FloorNumber 
            WHEN IS NOT NULL THEN --FloorNumber is given
                @Passed = 1
            ELSE --FloorNumber is required but is missing
                @Passed = 0
        END;
    ELSE --FloorNumber is not required
        @Passed = 1
END;

IF @Passed=1
    BEGIN

编辑:该解决方案只需要对 Daniel E 的稍作修正,建议的解决方案如下:

SELECT *
    ,CASE WHEN Inserted.FloorRef IN ('Floor', 'Level', 'Fl', 'L') THEN --FloorNumber is required
        CASE
            WHEN Inserted.FloorNumber IS NOT NULL THEN 1 --FloorNumber is given
            ELSE 0 --FloorNumber is required but is missing
        END
    ELSE 1 --FloorNumber is not required
    END [Passed]
FROM Inserted

【问题讨论】:

  • 为什么不在表上设置CHECK 约束而忘记触发器?
  • set @passed=CASE... 不是...THEN @passed=...
  • 因为触发器继续使用子查询对其他表中的字段进行检查。我可以将表级检查约束与一个代替触发器结合起来吗...?
  • @Daniel E,这解决了部分问题,现在它注意到“EXISTS IN”(“各种”、“不同”、“字符串”)处的语法不正确。如何将“IN”与“CASE”结合起来?
  • 如果您能详细说明您想要强制执行的实际限制条件,我们或许可以提供建议。

标签: sql-server if-statement case


【解决方案1】:

这将告诉您每行通过/失败,您可以根据需要使用这些结果。

SELECT * 
    ,CASE WHEN Inserted.FloorRef  IN ('Floor', 'Level', 'Fl', 'L') THEN --FloorNumber is required
             CASE WHEN Inserted.FloorNumber IS NOT NULL THEN 1 --FloorNumber is given
               ELSE 0 --FloorNumber is required but is missing                    
               END
     ELSE 1--FloorNumber is not required
     END [Passed]
FROM Inserted

【讨论】:

  • 啊,把我的眼睛从它身上移开,你抢了我的眼球。
  • 这看起来可以解决我的问题,尽管它给出了语法错误;知道为什么吗?问题在于这一行中的 IS:WHEN IS NOT NULL THEN 1 --FloorNumber is given
  • 除了= 比较之外,您不能使用简单的大小写表达式。内部的CASE 需要像外部的一样变成一个搜索的case 表达式(CASE 和第一个WHEN 子句之间没有)。
  • 那必须是CASE WHEN Inserted.FloorNumber IS NOT NULL THEN 1 ELSE 0 END
  • 谢谢各位大佬,我最后真的意识到了自己,然后看到了你们的回复。你是正确的,它需要是一个搜索过的案例。谢谢。
【解决方案2】:

Inserted 是一张表,您必须像对待它一样对待它。没有from子句。您还必须了解插入的可能有多条记录,因此您不能设置标量变量,如果某些记录应该传递 = 1 而其他记录应该是 0 会发生什么。触发器不能逐行工作!

我会按照 Damien 的建议改为查看检查约束。

【讨论】:

    【解决方案3】:

    正如其他人所说,请注意,当插入/更新/删除多行时,触发器中的 INSERTEDDELETED 伪表可以有多行,您需要处理这些。

    也就是说,这将检查第一个插入的行并设置 @Passed 位。

      DECLARE @FloorRef VARCHAR(20);
      DECLARE @FloorNumber  VARCHAR(20);
      DECLARE @Passed BIT = 0;
    
      SELECT TOP 1 @FloorRef = Inserted.FloorRef, @FloorNumber = Inserted.FloorNumber
      FROM INSERTED;
    
      SELECT @PASSED = CASE 
          WHEN @FloorRef IN ('Floor', 'Level', 'Fl', 'L') THEN --FloorNumber is required
              CASE
                  WHEN @FloorNumber IS NOT NULL THEN --FloorNumber is given
                      1
                  ELSE --FloorNumber is required but is missing
                      0
              END
           ELSE --FloorNumber is not required
              1
           END;
    

    SqlFiddle here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多