我非常习惯用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
答案 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