【问题标题】:Compound trigger invalid identifier复合触发器无效标识符
【发布时间】:2016-09-28 15:56:37
【问题描述】:

我有下表:

create table lessons(
id number,
name_teacher varchar2(9),
name_student varchar2(40),
start_lesson date, 
end_lesson date
);

我已经添加了这些数据:

insert into lessons values (001,'Peter','Thomas',to_date('2015-12-15','YYYY-MMDD'),to_date('2015-12-22','YYYY-MM-DD'));
insert into lessons values (002,'Eli','Alice',to_date('2015-06-16','YYYY-MMDD'),to_date('2015-06-23','YYYY-MM-DD'));
insert into lessons values (003,'Daniel','Thomas',to_date('2015-08-15','YYYY-MMDD'),to_date('2015-08-20','YYYY-MM-DD'));
insert into lessons values (001,'Peter','Alice',to_date('2015-12-16','YYYY-MM-DD'),to_date('2015-12-25','YYYY-MM-DD'));
insert into lessons values (002,'Eli','Thomas',to_date('2015-06-13','YYYY-MM-DD'),to_date('2015-06-20','YYYY-MM-DD'));

触发器无法添加的数据:

insert into lessons values (001,'Peter','Alice',to_date('2015-12-16','YYYY-MM-DD'),to_date('2015-12-25','YYYY-MM-DD'));
insert into lessons values (002,'Eli','Thomas',to_date('2015-06-13','YYYY-MM-DD'),to_date('2015-06-20','YYYY-MM-DD'));

我在 Oracle 中有这段代码,我尝试使用它来创建一个触发器,该触发器不允许我添加教师时间重叠的学生,例如“Peter”或“Eli”。

CREATE OR REPLACE TRIGGER lessons_trg
FOR INSERT OR UPDATE ON lessons
REFERENCING NEW AS New OLD AS Old
COMPOUND TRIGGER

 TYPE tbl_t IS RECORD(
 name_teacher VARCHAR2(9),
 start_lesson date,
 end_lesson date
 );
 TYPE tbl_typ IS  TABLE OF tbl_t;
 tbl tbl_typ;

  BEFORE STATEMENT IS
  BEGIN
   SELECT tbl_t(name_teacher, start_lesson, end_lesson)
   BULK COLLECT INTO tbl
   FROM lessons;
  END BEFORE STATEMENT;

  BEFORE EACH ROW IS
  v_count number;
  BEGIN
    SELECT COUNT(1)
    INTO v_count
    FROM TABLE(tbl) t
    WHERE t.name_teacher = :NEW.name_teacher
    AND :NEW.start_lesson BETWEEN t.start_lesson AND t.end_lesson
    AND :NEW.end_lesson BETWEEN t.start_lesson AND t.end_lesson;

    IF v_count > 0 THEN
      RAISE_APPLICATION_ERROR(-20000, 'Error');
    END IF;
  END BEFORE EACH ROW;
END;
/

问题是oracle给我以下错误:

Error(13,11): PL/SQL: ORA-00904: "TBL_T": invalid identifier
Error(23,10): PL/SQL: ORA-22905: cannot access rows from a non-nested table item
Error(23,16): PLS-00642: local collection types not allowed in SQL statements

感谢您的帮助和美好的一天:)

【问题讨论】:

  • 如错误消息所述,SQL 语句中不允许使用本地集合类型。您需要使用 create or replace type 单独定义它 - 但如果您这样做,使用全局临时表可能会更简单。
  • 顺便说一句,当您克服此语法错误时,您仍然会遇到触发器问题,该触发器允许两个会话添加彼此重叠的行。

标签: sql database oracle plsql triggers


【解决方案1】:

您需要将类型显式声明为数据库对象,而不是触发器中的组件。
试试这样的:

create or replace TYPE tbl_t IS object(
    name_teacher VARCHAR2(9),
    start_lesson date,
    end_lesson date
    );
 /
 create or replace TYPE tbl_typ IS TABLE OF tbl_t;
 /

不要忘记注释触发器主体中的类型声明。

【讨论】:

    【解决方案2】:
    create or replace 
    TYPE tbl_t as object(
     name_teacher VARCHAR2(9),
     start_lesson date,
     end_lesson date
     );
     /
     create TYPE tbl_typ IS  TABLE OF tbl_t;
     /
    create or replace 
    trigger lessons_trg
    FOR INSERT OR UPDATE ON lessons
    REFERENCING NEW AS New OLD AS Old
    COMPOUND TRIGGER
    
    
     tbl tbl_typ;
    
      BEFORE STATEMENT IS
      BEGIN
       SELECT tbl_t(name_teacher, start_lesson, end_lesson)
       BULK COLLECT INTO tbl
       FROM lessons;
      END BEFORE STATEMENT;
    
      BEFORE EACH ROW IS
      v_count number;
      BEGIN
        SELECT COUNT(1)
        INTO v_count
        FROM TABLE(tbl) t
        WHERE t.name_teacher = :NEW.name_teacher
        AND :NEW.start_lesson BETWEEN t.start_lesson AND t.end_lesson
        AND :NEW.end_lesson BETWEEN t.start_lesson AND t.end_lesson;
    
        IF v_count > 0 THEN
          RAISE_APPLICATION_ERROR(-20000, 'Error');
        END IF;
      END BEFORE EACH ROW;
    END;
    /
     insert into lessons values (001,'Peter','Thomas',to_date('2015-12-15','YYYY-MM-DD'),to_date('2015-12-22','YYYY-MM-DD'));
    insert into lessons values (002,'Eli','Alice',to_date('2015-06-16','YYYY-MM-DD'),to_date('2015-06-23','YYYY-MM-DD'));
    insert into lessons values (003,'Daniel','Thomas',to_date('2015-08-15','YYYY-MM-DD'),to_date('2015-08-20','YYYY-MM-DD'));
    insert into lessons values (001,'Peter','Alice',to_date('2015-12-16','YYYY-MM-DD'),to_date('2015-12-25','YYYY-MM-DD'));
    insert into lessons values (002,'Eli','Thomas',to_date('2015-06-13','YYYY-MM-DD'),to_date('2015-06-20','YYYY-MM-DD'));
    

    这应该可以工作

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-27
      • 2011-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多