PL/SQL触发器问题(将数据从表1复制到表2)

PL/SQL触发器问题(将数据从表1复制到表2),sql,database,oracle,plsql,triggers,Sql,Database,Oracle,Plsql,Triggers,我环顾四周,尝试了一些我读过的解决方案。我试图创建一个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_AP

我环顾四周,尝试了一些我读过的解决方案。我试图创建一个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:必须声明标识符“状态\u ID”

6.1 PL/SQL:忽略语句


您可能需要添加
新的

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;
看看这个:

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;

一旦注意到需要使用:NEW引用值以获取此插入或更新的ID状态的当前值,您将遇到第二个错误-您无法查询触发器所在的表,因为它的内容在不断变化。您将得到一个变异表错误。更不用说你在SELECT上没有where子句,所以你会将所有应用程序转储到APP_历史记录中。我敢打赌,你所希望的就是复制更新之前的行。当然,插入之前没有行,因此没有任何内容可以复制。还是要在插入时将新值复制到历史记录表中

假设您希望在更新时保留旧值,那么您将:

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。所以,如果你的用户界面设置了一个APP_ID值,然后使用该值插入相关记录,那么你就搞糟了

那么错误是什么?你有错误吗?或者你的触发器坏了?看起来我们只是在猜测。因为除了语法错误(缺少:new和错误的插入)之外,我们不知道您的查询应该做什么。另外,请阅读并不要忘记冒号-:new not NEWIF new.STATUS\u ID=2或new.STATUS\u ID=5或new.STATUS\u ID=7或new.STATUS\u ID=8,然后生成此错误编译失败,第6行(14:08:58)与编译错误关联的行号与第一个BEGIN语句相对。这只会影响数据库触发器的编译。PLS-00201:标识符'NEW.STATUS_ID'必须是declaredCompiled failed,第6行(14:08:58)与编译错误相关的行号与第一个BEGIN语句相关。这只会影响数据库触发器的编译。PL/SQL:Statement ignoredIF:new.STATUS\u ID=2或:new.STATUS\u ID=5或:new.STATUS\u ID=7或:new.STATUS\u ID=8然后生成此错误PL/SQL:ORA-00947:没有足够的值编译失败,第7行(14:07:38)与编译错误关联的行号与第一个BEGIN语句相关。这只会影响数据库触发器的编译。PL/SQL:SQL语句被忽略,如果我将其修复为:new。您能描述一下您的
app\u历史记录
表吗?我进行了更新以包含要插入的字段名。仅保留值history_id(通过触发器自动生成)、srn、app_date和status_id编译失败,第11行(14:11:22)与编译错误关联的行号与第一个BEGIN语句有关。这只会影响数据库触发器的编译。PL/SQL:ORA-00947:没有足够的值编译失败,第11行(14:11:22)与编译错误关联的行号与第一个BEGIN语句相关。这只会影响数据库触发器的编译。PL/SQL:SQL语句忽略所以也许你应该在你的insert语句中命名列,例如insert into app_history(column1,column2,column3)值(:new.srn,:new.status_id,:new.app_date)你的“app_history”表的结构是什么?@PT_STAR OP在我的回答中用注释描述该表,顺便说一下,如果要存储旧值,可以使用:old前缀(仅在更新时使用)。。。。如果更新,那么…为什么只更新
?触发器用于更新和插入通常历史记录表不包括当前行,这就是为什么在将:旧值复制到历史记录表之前,我询问了他/她的意图并解释了我的回答假设。我还解释了表的变化,我还想问为什么应用程序ID会在更新时发生变化。我当然希望这不是PK!不管怎样,只要给一个明显的初学者尽可能多的信息。事实上,如果你看一下触发器声明,它会在更新app_id时触发,然后会在触发器内再次更改app_id。哎哟第一次剪切的错误太多了,人们需要停下来,深呼吸,并对他们想要完成的任务有一个更清晰的定义。感谢您在我的代码中强调了另一个问题,在我和同事之间,我们从未想过每次更新都会更改主键。我将修改所有触发器以解决此问题。感谢Michael帮助我修复if声明和主要问题。