ORA-24344: 编译错误成功 - 触发 APEX

Posted

技术标签:

【中文标题】ORA-24344: 编译错误成功 - 触发 APEX【英文标题】:ORA-24344: success with compilation error - Trigger APEX 【发布时间】:2016-05-23 13:48:42 【问题描述】:

我一直在处理这个触发器,当我运行脚本时,它会告诉我之前的错误消息。我似乎无法弄清楚为什么它不能正确编译,每个 pl/sql 触发器教程似乎都有我的触发器的结构。代码如下:

create
    or replace trigger new_artist before insert
        on
        Artist referencing new as nvartist declare counter number;

begin select
    count( * ) into
        counter
    from
        Performer
    where
        Stage_name = nvartist.Stage_name;

if counter > 0 then signal sqlstate '45000';
else insert
    into
        Artist
    values(
        nvartist.Stage_name,
        nvartist.Name
    );

insert
    into
        Performer
    values(nvartist.Stage_name);
end if;
end;

它检查新艺术家是否已经存在于它的超类型(Performer)中,如果确实存在,它会给出错误,如果它不插入艺术家(Stage_name varchar2,Name varchar2)和Performer(Stage_name)。 Performer 的另一个子类型(与 Artist 同级)是 Band(Stage_name),它又与 Artist 有关系。为什么编译器会因为这个触发器对我大喊大叫?

提前致谢

【问题讨论】:

当您尝试在同一个基础表中插入数据时,由于发生变异触发器错误,它应该在运行时无论如何都会失败 我读到过,我知道如果触发器与插入/更新的行混淆,如果它直接或间接删除触发器内的该行,则触发器将失败,我不认为它是案子。我的目标是在插入 Artist 之前检查 Stage_name 是否已经存在于 Performer 中。如果它确实存在(因为它们是不相交的 isa(Performer ISA Artist/Band)),它会给出错误,但如果它不存在,它会同时插入 Artist 和 Performer。我认为这会实现。 Oracle´ 中没有 SIGNAL 命令。这是mysql。此触发器不会编译。而不是 Signal 使用 raise_application_error。您不能在同一个表中插入,也不需要。删除“插入艺术家”命令。这将自动完成。 【参考方案1】:

您可能想尝试这种变体(我稍微修改了您的表格名称)。 使用示例数据创建表:

CREATE table test_artist(
   stage_name varchar2(100)
 , name varchar2(100)
);

create table test_performer(
   stage_name varchar2(100)
);

/*inserting test performer on which trigger will rise an error*/
insert into test_performer
select 'performer_1' from dual;

创建触发器:

create or replace trigger new_artist
  before insert
  on TEST_ARTIST 
  referencing new as nvartist
  for each row

declare
  counter number;
begin
  select count(*)
  into counter
  from test_performer
  where Stage_name = :nvartist.Stage_name;

  if counter > 0 then
      --signal sqlstate '45000' ;
      raise_application_error( -20001, 'No insertion with existing Performer');
  else
      /*you cant update the same table, in other case you'll get 
      ora-04091 table mutating error.      
      But nevertheless this values will be inserted by sql triggered this trigger.*/
      --insert into test_artist values(:nvartist.Stage_name, :nvartist.Name);      
      insert into test_performer values(:nvartist.Stage_name);
  end if;
end new_artist;

之后此插入将起作用,因为'test_performer'表中没有'performer_2':

insert into test_artist
select 'performer_2', 'name_2' from dual;

这将失败:

insert into test_artist
select 'performer_1', 'name_1' from dual;

【讨论】:

感谢您的深入回答。我怀疑表发生了变异,但我不确定插入到 Artist 中是否仍然会发生。这里的“每一行”不是多余的吗?由于计数器将填充计数查询,我还需要检查每一行吗? 嗨,@朋克! “FOR EACH ROW 选项确定触发器是行触发器还是语句触发器。”您可以将每条语句插入许多行到“艺术家”表中,因此您似乎必须对每一特定行进行执行者存在检查。另一个:表级触发器中不允许使用 NEW 或 OLD 引用。

以上是关于ORA-24344: 编译错误成功 - 触发 APEX的主要内容,如果未能解决你的问题,请参考以下文章

尝试创建一个触发器来跟踪用户对表所做的更改但不断收到错误 ORA-24344:编译错误成功

ORA-24344: 尝试在 plsql 中创建函数时编译错误成功

函数创建时编译错误成功,为啥?

编译过程时出现oracle错误

Oracle 终止会话过程

For循环中触发失败