SQL Server - IF EXISTS同时执行TRUE分支和FALSE分支

时间:2016-05-04 11:39:13

标签: sql sql-server

我需要检查表中是否存在现有记录(用于员工评估)。如果存在此类记录,则查询必须获取该员工的最新条目,并计算下一个评估的下一个开始日期和结束日期。如果此类记录不存在,则查询必须应用不同的逻辑并计算第一次评估的新开始日期和结束日期(从当前日期开始倒计时)。

为了做到这一点,我在SQL Server中使用了IF EXISTS表达式,但似乎如果我为开始日期和结束日期变量保留了相同的名称,SQL就会覆盖它们(所以顺序执行分支,不挑选一个或另一个)。所以我宣布了两组变量来解决这个问题。但是,SQL Server似乎继续计算每个案例的开始日期和结束日期(EXISTS和NOT EXISTS)。我知道这是因为我要求它打印4个变量,所有变量都印有不同的值。

这是我(现在)4个变量的声明:

    IF EXISTS (SELECT main.[login] 
        FROM dbo.EVALUATIONS_TABLE eval
        WHERE eval.[login] = @login)
    SET @startdate = DATEADD(day, 1, (SELECT END_DATE FROM (SELECT TOP 1 ID, END_DATE FROM dbo.EVALUATIONS_TABLE WHERE [LOGIN] = @login) lastscorecard));
    SET @enddate = DATEADD(day, 10, @startdate);
ELSE
    SET @startdate_new = DATEADD(day, -1, GETDATE());
    SET @enddate_new = DATEADD(day, -10, @startdate_new);

我试图在输出表变量中插入一组或另一组变量,但我仍然必须依赖相同的IF EXISTS逻辑,这在我们上面看到的是不可靠的。 SQL Server如此困惑的原因是什么?我愿意重新考虑我的整个逻辑,以避免这样的混乱: - )

4 个答案:

答案 0 :(得分:2)

您需要使用BEGIN / END,否则只会运行IF之后的第一个语句:

const socketMock = {
  channel() {
    const channel = {
      join() { return channel },
      receive(msg, callback) {
        setTimeout(() => msg === 'ok' && callback(responseMock), 0)
        return channel
      },
      on() {},
      leave() {}
    }
    return channel
  }
}

答案 1 :(得分:1)

"显而易见"解决方案是使用begin / end作为if块。事实上,我建议始终使用begin / endif来防止此类错误。

但是,你可以完全摆脱if

SELECT @startdate = COALESCE(DATEADD(day, 1, MAX(END_DATE)),
                             DATEADD(day, -1 GETDATE)
                            )
FROM (SELECT TOP 1 et.*
      FROM dbo.EVALUATIONS_TABLE et.
      WHERE [LOGIN] = @login
     ) l;

SELECT @enddate = DATEADD(day, -10, @startdate);

答案 2 :(得分:0)

Iulia Mihet, 对于此类查询,您应始终使用BEGIN和END。特别是在使用有条件的IF EXISTS查询时。 您的代码应如下所示:

IF EXISTS (SELECT main.[login] 
    FROM dbo.EVALUATIONS_TABLE eval
    WHERE eval.[login] = @login)
BEGIN
SET @startdate = DATEADD(day, 1, (SELECT END_DATE FROM (SELECT TOP 1 ID, END_DATE FROM dbo.EVALUATIONS_TABLE WHERE [LOGIN] = @login) lastscorecard));
SET @enddate = DATEADD(day, 10, @startdate);
END
ELSE
BEGIN
SET @startdate_new = DATEADD(day, -1, GETDATE());
SET @enddate_new = DATEADD(day, -10, @startdate_new);
END

希望有所帮助

答案 3 :(得分:0)

您可以使用相同的变量。你有使用BEGIN和END。 使用以下查询。

IF EXISTS (SELECT main.[login] 
    FROM dbo.EVALUATIONS_TABLE eval
    WHERE eval.[login] = @login)
BEGIN
    SET @startdate = DATEADD(day, 1, (SELECT END_DATE FROM (SELECT TOP 1 ID, END_DATE FROM dbo.EVALUATIONS_TABLE WHERE [LOGIN] = @login) lastscorecard));
    SET @enddate = DATEADD(day, 10, @startdate);
END
ELSE
BEGIN
    SET @startdate = DATEADD(day, -1, GETDATE());
    SET @enddate = DATEADD(day, -10, @startdate_new);
END