您好我有以下脚本
CREATE OR REPLACE TRIGGER DOUBLE_BOOKINGS
BEFORE INSERT OR UPDATE ON BOOKING_SESSION
FOR EACH ROW
DECLARE
session_date TIMESTAMP;
session_room NUMBER;
BEGIN
SELECT start_session
INTO session_date --- EXISTING SESSION
FROM booking_session
WHERE bk_room = :NEW.bk_room;
IF session_date = :NEW.start_session THEN
RAISE_APPLICATION_ERROR
(-1000, 'Room is already booked');
END IF;
END;
/
该脚本可以将任何新预订与同一房间和同一日期的现有预订相匹配(以停止双重预订)
然而它无法正常工作。
SQL> INSERT INTO BOOKING_SESSION VALUES (45,TO_TIMESTAMP('18/03/2012 10:00', '
INSERT INTO BOOKING_SESSION VALUES (45,TO_TIMESTAMP('18/03/2012 10:00', 'DD/MM
*
ERROR at line 1:
ORA-04098: trigger 'U1146815.ROOM_BOOKED' is invalid and failed re-validation
start_session
是数据库列名,我在其中存储预订的日期和时间,并且是时间戳。 booking_session
是保存预订的名称,bk_room
保留了房间的数量。
因此,在提交预订之前,我尝试将new
预订日期与同一房间的旧预订日期相匹配,然后显示错误消息。
更新
新错误,似乎是返回太多行,我怎么能一次做一个。
ERROR at line 1:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "U1146815.DOUBLE_BOOKINGS", line 5
ORA-04088: error during execution of trigger 'U1146815.DOUBLE_BOOKINGS'
答案 0 :(得分:0)
您显然在ROOM_BOOKED
表上有另一个名为BOOKING_SESSION
的触发器。并且该触发器处于无效(未编译)状态。
如果您只想阻止具有重复bk_room / start_session值的记录,只需向表中添加唯一约束:
ALTER TABLE booking_session
add CONSTRAINT my_constraint UNIQUE (bk_room, start_session);
编辑:您的新错误是因为您在表中具有相同bk_room值的多个记录,这是预期的。但是,正如我在上面所述,你不需要触发器来防止重复,只需要一个独特的约束。
答案 1 :(得分:0)
如果在代码中使用SELECT...INTO
,则select必须返回一行。在其他情况下,它会抛出NO_DATA_FOUND异常或TOO_MANY_ROWS(您的情况)。您可以捕获这些异常,但它可能会使代码不清楚。最好使用光标来查询你的记录。
试试这个
CREATE OR REPLACE TRIGGER DOUBLE_BOOKINGS
BEFORE INSERT OR UPDATE ON BOOKING_SESSION
FOR EACH ROW
DECLARE
session_date TIMESTAMP;
session_room NUMBER;
CURSOR c_existing IS
SELECT start_session
FROM booking_session
WHERE bk_room = :NEW.bk_room and
session_date = :NEW.start_session;
dummy_session c_existing.start_session%TYPE;
BEGIN
OPEN c_existing;
FETCH c_existing INTO dummy_session;
IF c_existing%FOUND THEN
CLOSE c_existing;
RAISE_APPLICATION_ERROR
(-1000, 'Room is already booked');
END IF;
CLOSE c_existing;
END;
/