在预期条件的上下文中指定的非布尔类型的表达式,靠近'Begin'

时间:2013-09-10 15:30:39

标签: sql sql-server

我正在开展酒店项目,我需要检查房间的可用性。这里的逻辑首先需要检查房间可用性,如果它不可用,那么我需要检查客户输入的结账日期是否等于任何客户的结账日期:

ALTER PROCEDURE [dbo].[customerdetails] (@CheckIn     DATE, ...)
AS
  BEGIN
      BEGIN TRY
          IF ( (SELECT Available
                FROM   rooms
                WHERE  roomtype = @RoomType) > 0 )
            BEGIN
                INSERT INTO Customerdetail
                VALUES      (@CheckIn, ...)
            END
          ELSE IF(SELECT *
             FROM   Customerdetail
             WHERE  RoomType = @RoomType
                    AND CheckOut = @CheckOut)
            BEGIN
                INSERT INTO Customerdetail
                VALUES     (@CheckIn, ...)
            END
      END TRY

      BEGIN CATCH
          DECLARE @ErrMessage NVARCHAR(max)

          SET @ErrMessage=ERROR_MESSAGE()

          RAISERROR (@ErrMessage,16,1)
      END CATCH
  END 

但是我收到了一个错误:

  

Msg 4145,Level 15,State 1   
在“BEGIN”附近的预期条件的上下文中指定的非布尔类型的表达式。

2 个答案:

答案 0 :(得分:8)

问题实际上就在这里,您只需说IF (get result)

ELSE IF(SELECT *
             FROM   Customerdetail
             WHERE  RoomType = @RoomType
                    AND CheckOut = @CheckOut)

我认为这应该是IF (get result) = somethingIF something (about result),例如:

ELSE IF EXISTS (SELECT *
             FROM   Customerdetail
             WHERE  RoomType = @RoomType
                    AND CheckOut = @CheckOut)

保罗认为这条款不合适是正确的:

IF ( (SELECT Available
            FROM   rooms
            WHERE  roomtype = @RoomType) > 0 )

如上所述,如果返回多行,则会产生:

  

Msg 512,Level 16,State 1,Line 1   
子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。

因此,您应该按照他的建议使用EXISTS对此进行编码。

正如Martin在评论中所建议的那样,您还应确保在高并发性下测试此解决方案。

答案 1 :(得分:2)

变化:

IF ( (SELECT Available
            FROM   rooms
            WHERE  roomtype = @RoomType) > 0 )

为:

IF ( exists(SELECT Available
            FROM   rooms
            WHERE  roomtype = @RoomType) )