如何从 PL/SQL 中的触发器回滚列
Posted
技术标签:
【中文标题】如何从 PL/SQL 中的触发器回滚列【英文标题】:How to rollback a column from a trigger in PL/SQL 【发布时间】:2021-07-01 08:52:39 【问题描述】:我的任务有一个触发器。我更新了触发器,这意味着我在触发器中添加了 GL_TP 列。但在交付该部分之前,我还必须回滚该部分以撤消触发器中的该列。 那么如何使用 sql 查询撤消触发器中的 GL_TP 列? 我愿意接受每一个想法或建议?
CREATE OR REPLACE TRIGGER GL_DEF_TO_TRG
BEFORE INSERT OR DELETE OR UPDATE OF CDATE, CMPNY_DEF_ID, CUSER, DESCR, GL_DEF_ID,
MNY_TP_ID, ST, UDATE, UUSER, GL_TP ON FCBSADM.GL_DEF
FOR EACH ROW
DECLARE
BEGIN
IF INSERTING THEN
INSERT INTO MTTFOD.GL_DEF_TO
(SEQ_GLDEF_ID, GL_DEF_ID, DESCR, MNY_TP_ID, CMPNY_DEF_ID, ST, CDATE, CUSER, UDATE,
UUSER, CHANGE_TYPE, CHANGE_DATE, GL_TP)
VALUES
(MTTFOD.SEQ_GLDEF_ID.NEXTVAL, :NEW.GL_DEF_ID, :NEW.DESCR, :NEW.MNY_TP_ID,
:NEW.CMPNY_DEF_ID, :NEW.ST, :NEW.CDATE, :NEW.CUSER, :NEW.UDATE, :NEW.UUSER, 'I',
SYSDATE, :NEW.GL_TP);
ELSIF UPDATING THEN
INSERT INTO MTTFOD.GL_DEF_TO
(SEQ_GLDEF_ID, GL_DEF_ID, DESCR, MNY_TP_ID, CMPNY_DEF_ID, ST, CDATE, CUSER, UDATE,
UUSER, CHANGE_TYPE, CHANGE_DATE, GL_TP)
VALUES
(MTTFOD.SEQ_GLDEF_ID.NEXTVAL, :NEW.GL_DEF_ID, :NEW.DESCR, :NEW.MNY_TP_ID,
:NEW.CMPNY_DEF_ID, :NEW.ST, :NEW.CDATE, :NEW.CUSER, :NEW.UDATE, :NEW.UUSER, 'U',
SYSDATE,
NEW:GL_TP);
ELSIF DELETING THEN
INSERT INTO MTTFOD.GL_DEF_TO
(SEQ_GLDEF_ID, GL_DEF_ID, DESCR, MNY_TP_ID, CMPNY_DEF_ID, ST, CDATE, CUSER, UDATE,
UUSER, CHANGE_TYPE, CHANGE_DATE, GL_TP)
VALUES
(MTTFOD.SEQ_GLDEF_ID.NEXTVAL, :OLD.GL_DEF_ID, :OLD.DESCR, :OLD.MNY_TP_ID,
:OLD.CMPNY_DEF_ID, :OLD.ST, :OLD.CDATE, :OLD.CUSER, :OLD.UDATE, :OLD.UUSER, 'D',
SYSDATE, NEW:GL_TP);
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20001, 'ERROR: CODE:' || SQLCODE || ' MSG:' ||
SQLERRM || ' TRACE:' ||
SUBSTR(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE(), 1, 3000));
END;
【问题讨论】:
什么是“撤消 GP_TP 列”?这是否意味着 GL_TP 的值需要设置为 NULL 或者需要设置回更新前的值? @Koen Lostrie 它应该被删除。从我的触发器 我不明白你的意思......如果它需要被删除......你为什么不直接删除它? 这个触发器以前的版本是没有GL_TP的。所以在我们的工作中,如果我们提供一个开发,我们也应该提供如何撤消事情。也许到目前为止我没有很好地解释情况。我希望现在更清楚了? 如果我理解正确,您希望语句更改触发器,对吗?这对于 sql 语句是不可能的 - 您只能使用CREATE OR REPLACE trigger
语句创建触发器。因此,要恢复到旧版本,您必须运行以前版本的代码。
【参考方案1】:
您的解释有点不清楚,但我假设这就是您想要实现的目标。触发器执行后,将 GL_TP 列的值设置回旧值:
...
SYSDATE, NEW:GL_TP); --> note the typo here !
END IF;
-- to revert the change in GL_TP and set it to the old value
:NEW.GL_TP := :OLD.GL_TP;
-- or you could just set it to NULL like this
-- :NEW.GL_TP := NULL;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20001, 'ERROR: CODE:' || SQLCODE || ' MSG:' ||
SQLERRM || ' TRACE:' ||
SUBSTR(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE(), 1, 3000));
END;
请注意,您的代码中有几个拼写错误。你有 NEW:GL_TP
- 这不是有效的 oracle 语法,它应该是 :NEW.GP_TP
。
请注意,这不是回滚。 ROLLBACK 是 oracle 中的一个概念,表示撤消事务。没有“回滚列”之类的东西。
【讨论】:
以上是关于如何从 PL/SQL 中的触发器回滚列的主要内容,如果未能解决你的问题,请参考以下文章