缺少END - Mysql存储过程

时间:2016-03-01 06:01:58

标签: mysql stored-procedures

我非常习惯用TSQL编写,MySQL正在进行一些调整,但我认为我得到了大部分内容。我有一个存储过程,但不会让步,我已经阅读并重新阅读了100次,阅读了所有我能找到的错误但仍然没有运气。

在第11行和本声明的结尾处:

CREATE TEMPORARY TABLE ReturnAvalRooms (roomID int); 

我收到错误“Missing End”,即使这是我查询的开头。 我已检查并仔细检查所有内容是否已声明并设置为适当;但只是无法弄清楚为什么我会收到这个错误。

以下是存储过程的完整副本。

    CREATE PROCEDURE `Get_AvailRooms` (IN StartDate datetime, IN EndDate datetime, IN RoomType int)
BEGIN
    DECLARE PStartDate datetime;
    DECLARE PEndDate datetime;
    DECLARE PRoomType int;
    SET PStartDate = StartDate;
    SET PEndDate = EndDate;
    SET PRoomType = RoomType;

        CREATE TEMPORARY TABLE AvaliableNowRooms AS (SELECT idRooms FROM rooms WHERE RoomNextAvail < PStartDate AND RoomTypeID = PRoomType);
        CREATE TEMPORARY TABLE ReturnAvalRooms (roomID int); 

    DECLARE AvailRooms CURSOR FOR SELECT * FROM AvaliableNowRooms;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    DECLARE RoomID INT;

    OPEN AvailRooms;

    read_loop: LOOP

    FETCH AvailRooms INTO RoomID;
        IF done THEN
            LEAVE read_loop;
        END IF;

            DECLARE Bookings CURSOR FOR SELECT BookingStartDate, BookingEndDate, BookingRoomID FROM Booking WHERE BookingRoomID = RoomID AND BookingEndDate < PStartDate;
            DECLARE PBookingStartDate datetime;
            DECLARE PBookingEndDate datetime;
            DECLARE PBookingRoomID,

            OPEN Bookings

            Booking_Read: LOOP
            FETCH Bookings INTO PBookingStartDate, PBookingEndDate, PBookingRoomID;
            IF done THEN
                LEAVE Booking_Read;
            END IF;

            IF PBookingStartDate BETWEEN PStartDate AND PEndDate
                LEAVE Booking_Read;
            ELSE IF PBookingEndDate BETWEEN PStartDate AND PEndDate
                LEAVE Booking_Read;
            ELSE
                INSERT INTO ReturnAvalRooms (id) values (PBookingRoomid);
            END LOOP;
            CLOSE Bookings;
            END

    END LOOP;
    CLOSE AvailRooms;
    END

    SELECT * FROM ReturnAvalRooms

END

2 个答案:

答案 0 :(得分:2)

MySQL特别关注DECLARE语句的顺序。在一个街区内,必须首先出现。而且(我相信)HANDLERs必须是最后的声明。

我对你的程序想要返回的内容感到困惑。您似乎想要退回指定类型的所有房间,而且没有任何预订与指定期间重叠。

但是看一下程序中的逻辑,似乎预订某个房间没有行,那个房间就不会被退回。这看起来很奇怪。这让我感到困惑的是这应该归还什么。该规范被许多不必要的混乱所混淆。

整个rigmarole可以通过单个SQL语句来完成,这个语句更简单,更清晰,更高效。

DELIMITER $$

CREATE PROCEDURE `Get_AvailRooms` (IN PStartDate datetime, IN PEndDate datetime, IN PRoomType int)
BEGIN
-- rooms of the specified type which are "available" for the 
-- specified period.  A room is considered not available if 
-- the RoomNextAvail col has a date value later than the beginning
-- of the specified period, or there are one or more bookings that
-- overlap that period. If the specified StartDate is later than
-- the specified EndDate, then no rooms are available.
-- 
-- This query uses an "anti-join" pattern to return only rows 
-- in rooms which don't have a overlapping booking

   SELECT r.idRooms
     FROM rooms r
     LEFT
     JOIN Booking b
       ON b.BookingRoomID = r.idRooms
      AND b.BookingEndDate    >= PStartDate
      AND b.BookingStartDate  <= PEndDate
    WHERE b.idRooms IS NULL
      AND r.RoomTypeID        = PRoomType
      AND r.RoomNextAvail     < PStartDate
      AND          PStartDate < PEndDate
    ORDER BY r.idRooms;

END$$

DELIMITER ;

这只是第一次削减;它没有经过测试。我们可能希望将<=>=更改为<>,具体取决于我们是否考虑在上午10点结束的预订与期间重叠从上午10点开始。

答案 1 :(得分:0)

在过程的顶部声明变量。此外,您在THEN声明后未使用IF。纠正代码。此外,在关闭loop块之前,您将关闭IF

CREATE PROCEDURE `Get_AvailRooms` (IN StartDate datetime, IN EndDate datetime, IN RoomType int)
BEGIN
    DECLARE PStartDate datetime;
    DECLARE PEndDate datetime;
    DECLARE PRoomType int;
    DECLARE AvailRooms CURSOR FOR SELECT * FROM AvaliableNowRooms;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    DECLARE RoomID INT;
    DECLARE Bookings CURSOR FOR SELECT BookingStartDate, BookingEndDate,   BookingRoomID FROM Booking WHERE BookingRoomID = RoomID AND BookingEndDate < PStartDate;
    DECLARE PBookingStartDate datetime;
    DECLARE PBookingEndDate datetime;
    DECLARE PBookingRoomID,
    SET PStartDate = StartDate;
    SET PEndDate = EndDate;
    SET PRoomType = RoomType;

        CREATE TEMPORARY TABLE AvaliableNowRooms AS (SELECT idRooms FROM rooms WHERE RoomNextAvail < PStartDate AND RoomTypeID = PRoomType);
        CREATE TEMPORARY TABLE ReturnAvalRooms (roomID int); 

    OPEN AvailRooms;

    read_loop: LOOP

    FETCH AvailRooms INTO RoomID;
        IF done THEN
            LEAVE read_loop;
        END IF;

            OPEN Bookings

            Booking_Read: LOOP
            FETCH Bookings INTO PBookingStartDate, PBookingEndDate, PBookingRoomID;
            IF done THEN
                LEAVE Booking_Read;
            END IF;

            IF PBookingStartDate BETWEEN PStartDate AND PEndDate THEN
                LEAVE Booking_Read;
            ELSE IF PBookingEndDate BETWEEN PStartDate AND PEndDate THEN
                LEAVE Booking_Read;
            ELSE
                INSERT INTO ReturnAvalRooms (id) values (PBookingRoomid);
            END;
            END LOOP;
            CLOSE Bookings;
            END

    END LOOP;
    CLOSE AvailRooms;
    END

    SELECT * FROM ReturnAvalRooms

END