[英]Missing END - Mysql Stored Procedure
我非常習慣於使用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
MySQL特別注重DECLARE語句的順序。 在一個區塊中,這些必須首先出現。 而且(我相信)處理程序必須是最后的聲明。
我對您打算返回的程序感到困惑。 似乎您想返回指定類型的所有房間,對於這些房間,沒有與指定時間段重疊的預訂。
但是,看一下過程中的邏輯,似乎如果預訂給定房間的行沒有排,該房間將不會被退回。 這似乎很奇怪。 令我感到困惑的是,這到底應該返回什么。 大量不必要的混亂使規范變得模糊。
整個操作過程可以通過單個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點開始的期間重疊。
在過程頂部聲明變量。 同樣,您在IF
語句之后不使用THEN
。 更正代碼。 另外,在關閉IF
塊之前要關閉loop
。
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.