0
create or replace TRIGGER log_worlds BEFORE UPDATE OR INSERT ON worlds
DECLARE
ac VARCHAR2(50);
tab VARCHAR2(50);
world VARCHAR2(50);
BEGIN
IF UPDATING THEN
ac:='Aktualizacja';
END IF;
IF INSERTING THEN
ac:='Nowe';
END IF;
tab:='WORLDS';
world:='world_';
world:=world||cast(NEW_WORLD.NEXTVAL as VARCHAR2(10));
INSERT INTO log(ACTION_DATE,ACTION,TAB_NAME,ADDED_WORLD) VALUES(SYSDATE,ac,tab,world);
INSERT INTO worlds(WORLD_NAME) VALUES(world);
END;

有人可以帮我解决这个问题,错误信息是关于第 14 行的吗?当我的 APEX 应用程序针对表发出 DML 时,该触发器应该向日志表添加新值并更改世界表的主键值。

4

3 回答 3

1

我认为这是这条线:

world:=world||cast(NEW_WORLD.NEXTVAL as VARCHAR2(10));

如果您将其替换为:

world := world||to_char(NEW_WORLD.NEXTVAL);

它应该工作。

顺便说一句:在分配中直接使用nextval调用不适用于 11.x 之前的版本(不确定此处 x 的值)。

在 10.x 中,您需要声明一个变量,然后使用:

SELECT to_char(new_world.nextval)
   into world_num;
world := world || world_num;
于 2012-05-24T12:44:25.443 回答
1

直接的语法错误是假设NEW_WORLD是您创建的序列,您需要执行类似的操作

SELECT world ||
         cast( new_world.nextval as varchar2(10) )
  INTO world
  FROM dual;

而不是直接引用您的CAST.

我还不清楚你的触发器应该做什么。它至少会产生一个无限循环。每个INSERTonWORLDS都会导致触发器触发,这将生成一个INSERTon WORLDSwhich 将导致触发器触发,等等。当您超过最大递归深度时,Oracle 最终会引发错误。也许您希望这是一个行级触发器,而不是一个更改:new.world_name?值的语句级触发器。如果是这种情况,您可能想要类似的东西

create or replace TRIGGER log_worlds 
  BEFORE UPDATE OR INSERT ON worlds
  FOR EACH ROW
DECLARE
  ac VARCHAR2(50);
  tab VARCHAR2(50);
  world VARCHAR2(50);
BEGIN
  IF UPDATING THEN
    ac:='Aktualizacja';
  END IF;
  IF INSERTING THEN
    ac:='Nowe';
  END IF;
  tab:='WORLDS';
  world:='world_';
  select world || cast(new_world.nextval as varchar2(10)
    into world
    from dual;
  INSERT INTO log(ACTION_DATE,ACTION,TAB_NAME,ADDED_WORLD) 
    VALUES(SYSDATE,ac,tab,world);
  :new.world_name := world;
END;

这假定它world_name实际上不是主键。如果world_name是主键,那么在更新行时修改主键值是没有意义的——如果您正在执行INSERT.

于 2012-05-24T12:43:40.723 回答
1

您收到的错误表明您的代码中有一些我无法立即找到的语法错误。但是,我预计会出现另一个错误,因为 Oracle 不允许您在触发器所在的同一个表上的触发器内执行 DML 语句(选择、插入、更新、删除)。您的触发器位于表世界上,因此不允许您将记录插入到触发器内的表世界中。

于 2012-05-24T12:31:35.603 回答