我环顾四周,尝试了一些我读过的解决方案。我正在尝试创建一个pl / sql触发器,如果满足一个子句,它将数据从一个表复制到另一个表。我觉得我可能只是制造了一个愚蠢的语法错误,而不是一个完全的关键失败,但会感激一些帮助。
create or replace TRIGGER TRG_APPLICATIONS
BEFORE INSERT or UPDATE OF APP_ID, Status_id
ON APPLICATIONS
FOR EACH ROW
BEGIN
:new.APP_ID := SEQ_APP_ID.nextval;
:new.APP_DATE := SYSDATE;
IF STATUS_ID = 2 OR STATUS_ID = 5 OR STATUS_ID = 7 OR STATUS_ID = 8 THEN
INSERT INTO APP_HISTORY
SELECT SRN, STATUS_ID, APP_DATE
FROM APPLICATIONS;
END IF;
END;
这是错误
6 4 PLS-00201:标识符' STATUS_ID'必须声明
6 1 PL / SQL:忽略语句
答案 0 :(得分:2)
一旦您注意到您需要使用以下值引用这些值:NEW以获取此插入或更新的ID的STATUS的当前值,您将会遇到第二个错误 - 您无法查询其中的表触发器存在,因为其内容不断变化。你会得到一个变异表错误。更不用说您在SELECT上没有where子句,因此您将所有APPLICATIONS转储到APP_HISTORY中。我打赌你想要的就是复制更新之前的行。当然插入前没有行,所以没有什么可以复制的。或者您想将新值复制到插入时的HISTORY表中吗?
假设您希望将旧值保留在更新中,那么您将:
create or replace TRIGGER TRG_APPLICATIONS
BEFORE INSERT or UPDATE OF APP_ID, Status_id
ON APPLICATIONS
FOR EACH ROW
BEGIN
-- APP_ID better not be the PK or it is changing on UPDATE!
-- IF you only want this value set once on INSERT, wrap it in an IF INSERTING ... END IF; structure
:new.APP_ID := SEQ_APP_ID.nextval;
:new.APP_DATE := SYSDATE;
IF UPDATING AND ( :NEW.STATUS_ID = 2 OR :NEW.STATUS_ID = 5 OR :NEW.STATUS_ID = 7 OR :NEW.STATUS_ID = 8 )
THEN
INSERT INTO APP_HISTORY (SRN, STATUS_ID, APP_DATE)
VALUES (:OLD.SRN, :OLD.STATUS_ID, :OLD.APP_DATE);
END IF;
END;
关于你第一次触发触发器的其他想法 - 你的触发器在更新app_id时触发,但随后在触发器内再次更改app_id。因此,如果您的UI正在设置APP_ID值,然后使用该值插入相关记录 - 您只是搞砸了。
答案 1 :(得分:0)
可能您需要添加NEW
IF :NEW.STATUS_ID = 2 OR :NEW.STATUS_ID = 5
OR :NEW.STATUS_ID = 7 OR :NEW.STATUS_ID = 8 THEN
INSERT INTO APP_HISTORY (srn, status_id, app_date)
VALUES (:NEW.SRN, :NEW.STATUS_ID, :NEW.APP_DATE);
END IF;
答案 2 :(得分:0)
检查出来:
create or replace TRIGGER TRG_APPLICATIONS
BEFORE INSERT or UPDATE OF APP_ID, Status_id
ON APPLICATIONS
FOR EACH ROW
BEGIN
:new.APP_ID := SEQ_APP_ID.nextval;
:new.APP_DATE := SYSDATE;
IF :new.STATUS_ID = 2 OR
:new.STATUS_ID = 5 OR
:new.STATUS_ID = 7 OR
:new.STATUS_ID = 8 THEN
INSERT INTO APP_HISTORY (srn, status_id, app_date)
values (:new.srn, :new.status_id, :new.app_date);
END IF;
END;