SQL存储过程无效标识符

时间:2020-04-15 19:17:50

标签: sql oracle stored-procedures plsql

试图在oracle中编译该存储过程中的几个变量时,我得到了ORA-00904无效标识符,但无法弄清楚原因;所有有效的存储事件都在代码的DECLARE块中声明,并且架构中的变量也都已正确定义。 有没有人遇到此错误和/或知道如何解决?

这是正在使用的架构的DDL

CREATE TABLE history
("history_id" number(4) primary key,
  "history_dt" date not null,
  "history_time" timestamp not null,
  "booking_cost" varchar2(50) not null,
  "booking_status" varchar2(50) not null
);


CREATE TABLE attendees 
("attendee_id" number(8) primary key,
  "attendee_name" varchar2(50) not null,
  "attendee_class" number(4) not null,
  "attendee_school" varchar2(50) not null,
  "attendee_status" varchar2(50) not null
);


CREATE TABLE event 
("event_id" number(10) primary key,
  "event_name" varchar2(100) not null,
  "event_location" varchar2(100) not null,
  "event_size" number(4) not null,
  "start_dt" date not null,
  "end_dt" date not null,
  "class_restriction" number(4) not null,
  "school_restriction" varchar2(100) not null
);


CREATE TABLE reservation 
("reservation_id" number(3) primary key,
  "event" number(10) references event("event_id"),
  "attendee" number(8) references attendees("attendee_id"),
  "booking" number(4) references history("history_id"),
  "reservation_status" varchar2(50) not null
);

这些是我收到的错误消息

编译失败,第19行(15:38:10) PL / SQL:ORA-00904:“ END_DT”:无效的标识符编译失败,第18行(15:38:10)

PL / SQL:忽略SQL语句编译失败,第26行(15:38:10) PLS-00302:必须声明组件'EVENT_ID'编译失败,第26行(15:38:10) PL / SQL:ORA-00904:“保留”。“ EVENT_ID”:无效的标识符编译失败,第26行(15:38:10)

PL / SQL:忽略SQL语句编译失败,第36行(15:38:10) PL / SQL:ORA-00904:“ EVENT_ID”:无效的标识符编译失败,第35行(15:38:10)

PL / SQL:语句已忽略编译失败,第51行(15:38:10) PL / SQL:ORA-00947:值不足编译失败,第51行(15:38:10)

create or replace procedure Event_Planning
(arg_event_id in number, arg_student_id in number)

IS
ws_event_name varchar(100);
ws_capacity number;
ws_event_school varchar2(4);
ws_event_class number;

past_event exception;
capacity exception;
school exception;
class exception;

BEGIN
--Test for active event

select max(event_name) into ws_event_name from event
where event_id = arg_event_id and end_dt > SYSDATE;

if ws_event_name is null
then raise past_event;
end if;

--Test for capacity
select max(event_capacity) into ws_capacity from event JOIN reservation ON event.event_id = reservation.event_id
where event_id = arg_event
and event_capacity > reservation_size;

if ws_capacity is null
then raise capacity;
end if;

--Test for restricted school
select max(school_restriction) into ws_event_school from event
where event_id = arg_event_id;

if ws_event_school = arg_school
then raise school;
end if;

--Test for restricted class
select max(class_restriction) into ws_event_class from event
where event.id = arg_event;

if ws_event_class = arg_class
then raise class;
end if;

--Update reservation table
insert into reservation values
(Seq.nextval, arg_event, arg_student);

update reservation
set reservation_size = reservation_size + 1;

--Exceptions
Exception
when past_event
then raise_application_error(-20001, 'Event has passed');
when capacity
then raise_application_error(-20002, 'Event at capacity');
when school
then raise_application_error(-20003, 'Invalid school');
when class
then raise_application_error(-20004, 'Invalid class');

END;

3 个答案:

答案 0 :(得分:2)

要使其更有可能回答您的问题,请共享所有内容。

其中包括实际的错误消息。并且,如果您真的想变得很好,请为您的EVENT和RESERVATION表添加TABLE DDL(甚至包括一些数据)。

我太懒惰了,无法猜出你的模样,只是将查询更改为虚拟表以复制问题。

您尚未声明

ws_school
arg_school
ws_class
arg_class

编译时,编译器将返回问题的行号和目标。您指的是数据库不知道的事情。

enter image description here

建议 不要硬编码变量的数据类型定义。因为,表可以并且将改变。

相反,使它们动态化。

所以,不用说

WS_SCHOOL        VARCHAR2(4);

做类似的事情

WS_SCHOOL        TABLE.COLUMN%TYPE;

然后,当表更改时,代码不一定会中断。​​

答案 1 :(得分:0)

因为event_id是主键,所以不需要在过滤器上使用end_date。

select "event_name" into ws_event_name
from event
where "event_id" = arg_event_id;

这看起来很困惑,以下几列来自哪里:--- = ^^^ = --- -event_capacity -Reservation_size

select max("event_size") into ws_capacity
from event
join reservation
    on event."event_id" = reservation."event"
where "event_id" = arg_event_id
    and "event_size" > count("reservation_id");

event.id的语法错误,必须是event_id

select "class_restriction" into ws_event_class
from event
where "event_id" = arg_event_id;

插入预订表:

select count(*) into reserve_count
from reservation
where "event" = arg_event_id
   and "attendee" = arg_studen_id;

if reserve_count = 0
then
    insert into reservation values
    (Seq.nextval, arg_event_id, arg_student_id, null, "R");
end if;

--- note: that needs to declare reserve_count

使用count()填充与会者,然后无需更新预订表。

-- update reservation
-- set reservation_size = reservation_size + 1;

预订表:

CREATE TABLE reservation
("reservation_id" number(13) primary key,
 "event" number(10) references event("event_id"),
 "attendee" number(8) references attendees("attendee_id"),
 "booking" number(10) references history("history_id"),
 "reservation_status" varchar(1) not null
);

要合并为单个查询:

select count(*), "event_name", "class_restriction"
   into event_count, ws_event_name, ws_event_class
from event
where "event_id" = arg_event_id;

-- note: that needs to declare event_count

答案 2 :(得分:0)

默认情况下,Oracle标识符(例如表名和列名)不区分大小写,因此例如,您可以

select dummy, DUMMY, Dummy
from   dual;

但是,如果确实需要,也可以使用双引号来覆盖标准规则。

create table demo("123/Wow!" number);

SQL> desc demo

Name                                      Null?    Type
----------------------------------------- -------- ----------------------------
123/Wow!                                           NUMBER

由于双引号,您的表historyattendeesevent等具有区分大小写的小写列名,因此在使用它们时必须遵循相同的约定:

SQL> select count(event_id) from event;
select count(event_id) from event
             *
ERROR at line 1:
ORA-00904: "EVENT_ID": invalid identifier


SQL> select count("event_id") from event;

COUNT("EVENT_ID")
-----------------
                0

1 row selected.

除非有一些重要的原因,否则重新创建没有双引号的列名的表将是最简单的。

(此外,reservation有一个"event"列,而不是"event_id"。可能还有其他错别字-我没有检查整个内容。)

相关问题