【问题标题】:Errors when trying to create trigger (invalid identifer & sql ignored)尝试创建触发器时出错(无效的标识符和 sql 被忽略)
【发布时间】:2017-05-06 01:57:18
【问题描述】:

我在酒店数据库中工作。我正在尝试创建一个触发器,该触发器将在根据当前日期是否介于房间的 check_in 和 check_out 值之间进行任何新预订之前更改房间的可用性状态。

我的编译器日志中有 2 个错误:

在“每一行”上忽略的 SQL 语句

ora00904:“status_in”:无效标识符

我将不胜感激。

表格:

create table room(
    room_id number(3) constraint room_pk primary key,
    room_type varchar2(15) constraint room_fk references roomType,
    status char(1)
);

create table reservation(
    reservation_id number(6) constraint reservation_pk primary key,
    check_in date,
    check_out date, 
    room_id number(3),
    guest_id varchar2(5),
    foreign key (room_id) references room(room_id),
    foreign key (guest_id) references guest(guest_id)
);

触发器:

create or replace trigger room_status
before insert on reservation
for each row
declare
    status_in room.status%type;
    error1 exception;
begin

    select status
      into status_in
      from room
      where room_id = :old.room_id;

    if sysdate between :old.check_in and :old.check_out then
      update room
       set status_in = 'F'
       where room_id = :old.room_id;
    else
       update room
         set status_in = 'T'
         where room_id = :old.room_id;
    end if;

exception
  when error1 then
    raise_application_error(-20100,'Insert Cancelled');
end;

【问题讨论】:

  • 我必须说我更喜欢特定的 Y/N 指标而不是这些模糊的状态列表。我猜TF 的意思是TRUEFALSE,但是TRUE 是一个状态吗?将列命名为occupied_yn(和varchar2(1) not null,而我们正在使用它,加上一个只允许YN 的检查约束)将使事情更清晰。

标签: sql oracle plsql triggers


【解决方案1】:

update 语句尝试更新status_in 的列room

update room
  set status_in = 'F'

room 没有该列。它有一个status 列。

我也不确定您在检索旧房间状态方面的意图。你打算用它来检查什么吗?如果不是,您的触发器是否会执行以下操作:

update room
  set status = (sysdate between :old.check_in and :old.check_out)
  where room_id = :old.room_id
;

如果是这样,那么您可能还会质疑您是否真的想要room 表中的status 列。 status 实际上是一个派生列。设置status 而不是计算它会给您带来不一致的危险。相反,您可以按照以下方式做一些事情:

create table room(
    room_id number(3) constraint room_pk primary key,
    room_type varchar2(15) constraint room_fk references roomType
);

查询:

SELECT r.room_id
      ,r.room_type
      ,SUM(CASE WHEN sysdate between :old.check_in and :old.check_out THEN 1 ELSE 0 END) AS status
  FROM room r
  JOIN reservation v ON (v.room_id = r.room_id)
  GROUP BY r.room_id, r.room_type
  ;

【讨论】:

  • 感谢您的回复!触发器编译得很好,但现在我收到错误:01403:找不到数据。我正在使用这个插入语句来检查:插入保留值(reservation_sequence.nextval,to_date('05-03-2017','mm/dd/yyyy'),to_date('05-07-2017','mm/ dd/yyyy'), '107', 'G180')
  • select ... into 会抛出 no data found 异常。那么有没有价值107的房间呢?约束是否有效? (另外,插入时不要引用数字)
猜你喜欢
  • 2015-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-28
  • 2021-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多