【问题标题】:Why Does this Procedure throw an error at Else when Compiling为什么此过程在编译时会在 Else 处抛出错误
【发布时间】:2016-02-03 09:33:38
【问题描述】:

当记录落在两个日期之间时,查看表中的字段是否等于 true 的相当简单的 sql 过程。目的是计算 tue 的实例,如果计数超过一个,则在输出参数中返回 true。

    CREATE PROCEDURE dbo.CheckIfLandingsForPeriodHaveBeenPosted @startDate DATE,
@endDate DATE,
@LandingsPosted BIT OUTPUT

AS
BEGIN
  SET NOCOUNT ON


  IF (SELECT 
        COUNT (
        lh.Posted
      FROM LandingHeaders lh
      WHERE lh.LandingDate1 BETWEEN @startDate AND @endDate
      AND lh.Posted = 1)
    > 0
    SET @LandingsPosted = 1
  ELSE
    SET  @LandingsPosted = 0

END
GO

我尝试在 lh.Posted = 1 之后添加一个额外的括号,并在 ELSE 之后立即删除 SET 语句,但都没有帮助。

首先我想知道为什么这在 else 语句中失败了,但我也想知道是否有一种更优雅/更有效的方法来首先创建这样的查询;就伪代码而言,类似于:

检查这两个日期之间记录中的发布字段,如果发现为真,则返回真

【问题讨论】:

  • 你缺少一个")'来关闭计数功能
  • 您在 lh.Posted 之后错过了一个 ')' 吗?我认为应该是 select count(lh.posted) from ....
  • 我真是太愚蠢了,我一直把多余的括号放在最后。
  • 如果您只关心 no 行和 any 行之间的区别,请使用 EXISTS 而不是要求系统 计数行数,然后将该值与零进行比较。系统有可能会愚蠢到实际检查所有行并计算它们,而不是在看到符合条件的行时立即完成。
  • @Damien_The_Unbeliever 谢谢,我认为可能有更有效的方法来解决这个问题,诚然,一开始只有大约 15 到 20 条记录可以计算,但我知道如果查询设计得当,sql 会非常高效。

标签: sql sql-server-2014-express


【解决方案1】:

完全避免IF ... ELSECOUNT 的紧凑且更高效的解决方案:

CREATE PROCEDURE dbo.CheckIfLandingsForPeriodHaveBeenPosted
    @startDate DATE, @endDate DATE,
    @LandingsPosted BIT = 0 OUTPUT   --<- Set default to FALSE
AS
BEGIN
    SELECT TOP 1 @LandingsPosted = 1 --<- Change to TRUE if at least one match is found
    FROM LandingHeaders lh
    WHERE lh.LandingDate1 BETWEEN @startDate AND @endDate
      AND lh.Posted = 1
END
GO

【讨论】:

    【解决方案2】:

    您忘记用) 关闭COUNT 请尝试以下操作:

        CREATE PROCEDURE dbo.CheckIfLandingsForPeriodHaveBeenPosted @startDate DATE,
    @endDate DATE,
    @LandingsPosted BIT OUTPUT
    
    AS
    BEGIN
      SET NOCOUNT ON
    
    
      IF (SELECT 
            COUNT(lh.Posted)
          FROM LandingHeaders lh
          WHERE lh.LandingDate1 BETWEEN @startDate AND @endDate
          AND lh.Posted = 1)
        > 0
        SET @LandingsPosted = 1
      ELSE
        SET  @LandingsPosted = 0
    
    END
    GO
    

    【讨论】:

      【解决方案3】:

      这是一个简单的语法问题,您可以看到我所做的唯一更改是在计数中,您缺少一个 ')',因此您的查询无法编译。

      过程抛出错误并不总是告诉你问题出在哪里,你总是可以假设问题出在它所说的地方。

      CREATE PROCEDURE dbo.CheckIfLandingsForPeriodHaveBeenPosted @startDate DATE,
       @endDate DATE,
       @LandingsPosted BIT OUTPUT
      
      AS
      BEGIN
        SET NOCOUNT ON
      
      
       IF (SELECT 
          COUNT (lh.Posted)
        FROM LandingHeaders lh
        WHERE lh.LandingDate1 BETWEEN @startDate AND @endDate
        AND lh.Posted = 1)
      > 0
      SET @LandingsPosted = 1
      ELSE
      SET  @LandingsPosted = 0
      
      END
      GO
      

      【讨论】:

        猜你喜欢
        • 2013-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-19
        • 1970-01-01
        • 1970-01-01
        • 2023-03-30
        • 2021-07-26
        相关资源
        最近更新 更多