2016-03-01 36 views
0

我非常習慣在TSQL中編寫代碼,MySQL正在進行一些調整,但我認爲我已經掌握了大部分內容。我有一個存儲過程,但不會讓步,我已經閱讀並重讀了100次,閱讀了所有我能找到的錯誤,但仍然沒有運氣。Missing END - Mysql存儲過程

在11號線及本聲明的末尾:

CREATE TEMPORARY TABLE ReturnAvalRooms (roomID int); 

我得到的錯誤「缺少結束」,儘管這是在我的查詢的開始。 我已經檢查並重新檢查了所有內容都被聲明並設置爲合適的;但只是無法弄清楚爲什麼我得到這個錯誤。

下面是存儲過程的完整副本。

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 

回答

1

MySQL特別關注DECLARE語句的順序。在一個街區內,那些必須先出現。而且(我相信)HANDLER必須是最後的聲明。

我很困惑你的程序打算返回什麼。您似乎希望返回指定類型的所有房間,但沒有任何與指定時間段重疊的預訂。

但是看看過程中的邏輯,看起來好像如果預定中沒有給定房間的行,那個房間將不會被返回。這似乎很奇怪。這讓我對這個應該回歸的東西感到困惑。規範被大量不必要的混亂所迷惑。

整個rigmarole可以通過一個簡單,更清晰,更有效的引導來實現。

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 ; 

這只是第一次切割;它沒有經過測試。我們可能想要將<=>=更改爲<>,具體取決於我們是否考慮以10AM結束的預訂與從上午10點開始的期間重疊。

+0

+10對於風格 - 給了這個查詢幾個現在進行了一些改動,以解釋新創建的房間有一個無效的日期,到目前爲止我不能錯。最初的理論,如果你想知道的是第一個臨時表將捕獲所有可用的房間,無論未來的預訂。一旦發生這種情況,它可以通過帶有roomID的預訂表循環,並收集所有未來的預訂,檢查交叉日期,然後將其添加到臨時表(如果沒有)。你的更好。謝謝!測試繼續... – Caz1224

0

聲明過程頂部的變量。 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 
+0

我希望我可以將兩個標記爲正確,你的回答是正確的並且修正了原來提出的問題,儘管斯賓塞提出了一個更好的解決方案。 – Caz1224

+0

「但只是不知道爲什麼我得到這個錯誤。」我只是讓你的proc錯誤免費。至少如果您發現答案正確,您可以加註。 – FallAndLearn