运行创建的过程时出现 Oracle 错误

标签 oracle plsql procedure

我有基于酒店房间住宿的 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.

我做错了什么?

最佳答案

您收到错误,因为 PL/SQL 中的 SELECT INTO 构造必须恰好返回 1 行。您的第一个选择没有返回任何行,因此会引发 NO_DATA_FOUND 错误。

如果有 2 行(例如 1 月的预订,2 月的预订),则会引发 TOO_MANY_ROWS 错误。

您想要做的是确保插入时没有重叠。例如,以下查询将返回一段时间内的所有预订:

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

请注意,我将 stay_fromv_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

关于运行创建的过程时出现 Oracle 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15094076/

相关文章:

oracle - Oracle 中的显式游标和隐式游标有什么区别?

mysql - mysql 数据库错误过程

procedure - 序言 : Making a procedure to print Hello World

php - 是否可以将数据传递给 Oracle 触发器?

sql - 这个 FIRST_VALUE 查询有什么问题?

asp.net - DB 中的 Oracle 字符串大于 UI 中的

oracle - 嵌套 block 对 PL/SQL 过程中的性能有影响吗?

ruby-on-rails - 在 ubuntu 14.04 x64 上安装 ruby​​-oci8 时出错

sql - 执行匿名 block PlSQL 失败

mysql - mysql的问题从 Doctrine 原始sql创建过程