【问题标题】:SQL Stored Procedure Invalid IdentifierSQL 存储过程无效标识符
【发布时间】:2020-04-15 19:17:50
【问题描述】:

当我尝试在 oracle 中编译此存储过程中的几个变量时,我得到 ORA-00904 Invalid Identifier 但不知道原因;所有工作存储事件都在代码的 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": invalid identifierCompilation failed,line 18 (15:38:10)

PL/SQL:SQL 语句被忽略编译失败,第 26 行 (15:38:10) PLS-00302:必须声明组件“EVENT_ID”编译失败,第 26 行 (15:38:10) PL/SQL: ORA-00904: "RESERVATION"."EVENT_ID": invalid identifierCompilation failed,line 26 (15:38:10)

PL/SQL: SQL 语句被忽略编译失败,第 36 行 (15:38:10) PL/SQL: ORA-00904: "EVENT_ID": invalid identifierCompilation failed,line 35 (15:38:10)

PL/SQL:语句忽略编译失败,第 51 行 (15:38:10) PL/SQL: ORA-00947: not enough valuesCompilation failed,line 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;

【问题讨论】:

  • 创建过程AS
  • @EduardoAlmeida 创建或替换过程 X 是...就好了
  • 如果您要显示实际的、完整的和完整的错误消息,它将帮助我们了解我们需要将注意力集中在哪里。顺便说一句,您对“工作存储”一词的使用——没有错——自从我作为 COBOL 程序员的日子以来,我就没有听说过这个词! :-)
  • @EduardoAlmeida 我相信下次轮到你来接我了 :)
  • @EduardoAlmeida 尽管is/as 关键字在这里可以互换,但create procedure xxx as 读起来更好。 procedure xxx is 在包中更有意义。

标签: sql oracle stored-procedures plsql


【解决方案1】:

为了让您的问题更有可能得到解答,请分享所有内容。

这包括实际的错误消息。如果您真的想变得更好,请为您的 EVENT 和 RESERVATION 表包含 TABLE DDL(甚至是一些数据)。

我太“懒惰”来猜测你的样子,只是将你的查询更改为虚拟表以复制问题。

你还没有声明

ws_school
arg_school
ws_class
arg_class

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

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

相反,让它们动态化。

所以,不要说

WS_SCHOOL        VARCHAR2(4);

做类似的事情

WS_SCHOOL        TABLE.COLUMN%TYPE;

那么当你的表发生变化时,你的代码不一定会中断。​​

【讨论】:

  • 我现在将添加有关错误的信息,如果您可以检查的话!问题不在于“ws”变量,而在于原始模式 DDL 中声明的变量。非常感谢你! :-)
  • 您的代码无法按原样编译...您正在将数据选入不存在的事物中。
  • 您需要向我们展示您选择“INTO”的所有表格的表格 ddl
  • 我不确定你想查看哪些表的 ddl
  • 您的列名区分大小写,您的查询需要反映这一点...将很快更新我的答案
【解决方案2】:

默认情况下,表名和列名等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"。可能还有其他类似的拼写错误 - 我还没有检查整个事情。)

【讨论】:

    【解决方案3】:

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

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

    这看起来很令人困惑,以下列来自哪里:---=^^^=--- -- 事件容量 -- 预留大小

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-30
      • 1970-01-01
      • 2022-01-25
      • 2013-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多