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时,此触发器应该向日志表添加新值并更改worlds表的主键值。
答案 0 :(得分:1)
您收到的错误表明您的代码中存在一些语法错误,我无法立即找到。但是我希望另一个错误,因为Oracle不会允许你在触发器打开的同一个表的触发器内执行DML语句(选择,插入,更新,删除)。您的触发器位于表格世界中,因此不允许您在触发器内的表格世界中插入记录。
答案 1 :(得分:1)
立即语法错误是假设NEW_WORLD
是您创建的序列,您需要执行类似
SELECT world ||
cast( new_world.nextval as varchar2(10) )
INTO world
FROM dual;
而不是直接引用CAST
中的序列。
我很清楚你的触发器应该做什么。它至少会产生一个无限循环。 INSERT
上的每个WORLDS
都会导致触发器触发,这会在INSERT
上生成WORLDS
,导致触发器触发,等等。超过最大递归深度时出错。也许您打算将其作为行级触发器而不是更改: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
,则只希望分配主键。
答案 2 :(得分: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;