Ошибка Oracle при запуске созданной процедуры

У меня есть база данных Oracle на основе пребывания в гостиничном номере. Я создал процедуру Room_taken и не могу заставить ее работать.

Это код моей процедуры SQL:

CREATE
PROCEDURE Room_taken
(
v_guestID IN NUMBER DEFAULT NULL ,
v_stayfrom IN DATE DEFAULT NULL ,
v_stayto IN DATE DEFAULT NULL ,
v_roomID IN NUMBER DEFAULT NULL ,
v_paymentID IN NUMBER DEFAULT NULL ,
v_totalprice IN NUMBER DEFAULT NULL 
)
AS
v_nofrom DATE;
v_noto DATE;
v_idroom NUMBER(10,0);

BEGIN

BEGIN
SELECT Stay_from, Stay_to     
INTO v_nofrom, v_noto
FROM Stayover
WHERE ID_room = v_roomID;
IF NOT ( v_nofrom >= v_stayfrom
AND v_noto <= v_stayto ) THEN

BEGIN
INSERT INTO Stayover
( Stay_from, Stay_to, Total_price, ID_Room, ID_Guest, ID_Payment )
VALUES ( v_stayfrom, v_stayto, v_totalprice, v_roomID, v_guestID, v_paymentID );
END;
ELSE

BEGIN
raise_application_error( -20002, 'Room is taken!' );
END;
END IF;
END;
END;

Когда я запускаю процедуру после ввода следующих параметров:

DECLARE
v_guestID NUMBER;
v_stayfrom DATE;
v_stayto DATE;
v_roomID NUMBER;
v_paymentID NUMBER;
v_totalprice NUMBER;
BEGIN
v_guestID := 1;
v_stayfrom := '17.01.2012';
v_stayto := '19.01.2012';
v_roomID := 1;
v_paymentID := 1;
v_totalprice := 300;

Room_taken(
v_guestID => v_guestID,
v_stayfrom => v_stayfrom,
v_stayto => v_stayto,
v_roomid => v_roomid,
v_paymentID => v_paymentID,
v_totalprice => v_totalprice
);
END;

У меня возникла ошибка:

Connecting to the database HOTEL.
ORA-01403: no data found
ORA-06512: at "HOTEL_ROOMS.ROOM_TAKEN", line 18
ORA-06512: at line 16
Process exited.
Disconnecting from the database HOTEL.

Что я делаю не так?


person Drazen    schedule 26.02.2013    source источник


Ответы (2)


Вы получаете сообщение об ошибке, поскольку конструкция SELECT INTO должна возвращать ровно 1 строку в PL/SQL. Ваш первый выбор не возвращает строку, поэтому возникает ошибка NO_DATA_FOUND.

Если бы было 2 строки (например, резервирование в январе, другое в феврале), вместо этого возникала бы ошибка TOO_MANY_ROWS.

Вместо этого вы хотите убедиться, что при вставке не будет перекрытия. Например, следующий запрос вернет все бронирования за период:

SELECT * 
  FROM Stayover 
 WHERE ID_room = v_roomID
   AND stay_from <= v_stayto 
   AND stay_to >= v_stayfrom 

Заметьте, я сравнил stay_from с v_stayto, это не опечатка.

Вы можете включить приведенный выше запрос в свой код примерно так:

CREATE OR REPLACE PROCEDURE Room_taken(v_guestID    IN NUMBER,
                                       v_stayfrom   IN DATE,
                                       v_stayto     IN DATE,
                                       v_roomID     IN NUMBER,
                                       v_paymentID  IN NUMBER DEFAULT NULL,
                                       v_totalprice IN NUMBER DEFAULT NULL) AS
   l_nb_reservation NUMBER;
BEGIN
   SELECT COUNT(*)
     INTO l_nb_reservation
     FROM Stayover
    WHERE ID_room = v_roomID
      AND stay_from <= v_stayto
      AND stay_to >= v_stayfrom;
   IF l_nb_reservation > 0 THEN
      raise_application_error(-20002, 'Room is taken!');
   END IF;

   INSERT INTO Stayover
      (Stay_from, Stay_to, Total_price, ID_Room, ID_Guest, ID_Payment)
   VALUES
      (v_stayfrom, v_stayto, v_totalprice, v_roomID, v_guestID, v_paymentID);
END;

Теперь вы сможете забронировать номер только один раз за период:

SQL> EXEC Room_taken(1, trunc(SYSDATE), trunc(SYSDATE), 1);

PL/SQL procedure successfully completed

SQL> EXEC Room_taken(1, trunc(SYSDATE), trunc(SYSDATE), 1);

begin Room_taken(1, trunc(SYSDATE), trunc(SYSDATE), 1); end;

ORA-20002: Room is taken!
ORA-06512: à "APPS.ROOM_TAKEN", ligne 16
ORA-06512: à ligne 2
person Vincent Malgrat    schedule 26.02.2013
comment
Я понял. Теперь я могу ввести новые данные о пребывании в таблице, но с вашим кодом я не могу вызвать ошибку «Комната занята», если в той же комнате уже кто-то есть... Вот почему мне нужна эта процедура. Я все еще в замешательстве, как это сделать. - person Drazen; 26.02.2013
comment
@drazen вы вставляете в таблицу NOCENJE и сверяете с таблицей STAYOVER. Если вы используете один и тот же стол в обоих случаях, вы должны получить номер занят! ошибка в случае предварительного бронирования. - person Vincent Malgrat; 26.02.2013
comment
Извини, я виноват. Я указал неправильный столбец в коде... Он работает, большое спасибо :) - person Drazen; 26.02.2013

Сообщение об ошибке
ORA-01403: данные не найдены

Причина ошибки

Вы пробовали одно из следующих действий:

  1. Вы выполнили оператор SELECT INTO, и строки не были возвращены.
  2. Вы сослались на неинициализированную строку в таблице.
  3. Вы читаете за конец файла с пакетом UTL_FILE.

Чтобы показать предлагаемое решение
Перейдите по этой ссылке
http://www.techonthenet.com/oracle/errors/ora01403.php

person ahmednabil88    schedule 26.02.2013