为什么" INTERVAL"在IF语句中不是有效的语法

时间:2016-09-05 15:20:03

标签: mysql sql

我在其中一个存储的prodecures中有一个IF THEN ELSE语句。

 if (DAYOFWEEK((SELECT  DATE_ADD(_todaydate, INTERVAL (_sign * offset.value) DAY)))=7) 
 then
        SELECT  DATE_ADD(daytemp, INTERVAL (_sign * offset.value + 2) DAY) into `day`;
 elseif (DAYOFWEEK((SELECT  DATE_ADD(_todaydate, INTERVAL _sign * offset.value DAY)))=1) 
 then
        SELECT  DATE_ADD(daytemp, INTERVAL (_sign * offset.value + 1) DAY) into `day`;
 else
        Select (SELECT  DATE_ADD(_todaydate, INTERVAL _sign * offset.value DAY)) into `day`;
 END if;

其中_todaydate是今天的日期,_sign可以是+1-1,具体取决于您是否希望在将来或过去找到日期和{ {1}}是一个数字int,表示offset的天数。

该查询是为了在过去或将来返回工作日,具体取决于_todaydate,但问题是sql返回错误说_sign * offset.value

我不知道为什么我会遇到这个问题因为查询它本身对我来说很好。有人可以看看我错过了什么......

其他信息:

我在"选择来自"声明,这可能是发生这种错误吗?

2 个答案:

答案 0 :(得分:3)

您的IF声明不应如下所示

if (SELECT DAYOFWEEK(DATE_ADD(_todaydate, INTERVAL (_sign * offset.value) DAY))=7)

此外,我发现您多次重复相同的条件,最终多次执行相同的查询。而是在此之前执行此查询并将值存储到局部变量并在条件语句中使用该局部变量;这将是非常有效的。

答案 1 :(得分:1)

如果我们避免重复长表达式,那么代码就不会更容易调试和理解,写下这样的东西(完成我们试图实现的目标):

  DECLARE _dow INT;
  DECLARE _inc INT;

  SELECT DAYOFWEEK(DATE_ADD(_todaydate, INTERVAL (_sign * offset.value) DAY)) INTO _dow ;

  CASE _dow
    WHEN 7 THEN SET _inc = 2;
    WHEN 1 THEN SET _inc = 1;
    ELSE        SET _inc = 0;
  END CASE;  

  SELECT DATE_ADD(daytemp, INTERVAL (_sign * offset.value + _inc) DAY) INTO `day`;

要回答您提出的问题,“为什么INTERVAL不是IF语句中的有效语法”......

我不知道MySQL存储程序中的任何限制都禁止在IF语句中使用关键字INTERVAL。显然,INTERVAL关键字不是IF构造的一部分;关键字仅在某些表达式的上下文中有效。

<强>后续

我注意到上面的重写不等同于原文。在原文中,在ELSE条件下,它是 DATE_ADD(_todaydate, 。这与其他两个条件不同,即 DATE_ADD(daytemp

稍微重写以适应这种差异,添加另一个变量_bdt,允许我们仍然只使用两个SELECT语句......

  DECLARE _bdt DATE;
  DECLARE _dow INT;
  DECLARE _inc INT;

  SELECT DAYOFWEEK(DATE_ADD(_todaydate, INTERVAL (_sign * offset.value) DAY)) INTO _dow ;

  CASE _dow
    WHEN 7 THEN 
      SET _inc = 2;
      SET _bdt = daytemp; 
    WHEN 1 THEN
      SET _inc = 1;
      SET _bdt = daytemp;
    ELSE
      SET _inc = 0;
      SET _bdt = _todaydate;
  END CASE;  

  SELECT DATE_ADD(_bdt, INTERVAL (_sign * offset.value + _inc) DAY) INTO `day`;