如何知道在Oracle中更新,删除或插入了哪些记录

时间:2011-05-30 08:04:26

标签: oracle plsql triggers

我正在做一个LogTable,我在那里保存了在RealTable上修改过的数据。

根据数据,我的意思是我需要恢复整个记录的:new:old值。所以我有一个触发器来响应是否有插入,删除或更新。

所以我的问题是:我如何知道哪条记录被更改以及如何恢复它的内容?

示例:

create table t1(
    a integer,
    b integer
)

create table LogT1(
    new_a integer, 
    old_a integer,
    new_b integer,
    old_b integer
)

假设在t1上有一条记录,其值为a = 1,b = 2且t1得到更新,因此记录将值更改为a = 3,b = 4

因此更新激活了触发器,它必须:

  1. 了解哪条记录已被修改。
  2. 恢复该记录。
  3. 获取“之前”和“之后”a和b值
  4. 将这些值作为old_a,new_a,ol​​d_b,new_b
  5. 插入LogT1

    在LogT1上作为插入而得到值new_a = 3,old_a = 1,new_b = 4,old_b = 2

    CREATE or REPLACE TRIGGER tr001
      AFTER INSERT OR UPDATE OR DELETE ON t1
    
    DECLARE
    
        a integer;
        b integer;
        a2 integer;
        b2 integer;
    
    BEGIN
    
        IF DELETING THEN 
    
            *Recover the row that changed* 
    
            *Then use that row*
            a2:= :new.a ;
            b2:= :new.b ;
            a:= :old.a ;
            b:= :old.b ;
            insert into LogT1 (new_a integer, old_a integer, new_b integer, old_b integer) 
    values (a2,a,b2,b);
    
        END IF;
    
    ....
    
    END tr001;
    

    我是新来的,所以如果我的问题不合适,我最诚挚的道歉。

4 个答案:

答案 0 :(得分:4)

据我所知,您可以将触发器声明为FOR EACH ROW,以便为删除|插入|更新的每一行触发它,然后:new和:old包含特定的行值。希望这会有所帮助。

CREATE or REPLACE TRIGGER tr001 
  AFTER INSERT OR UPDATE OR DELETE 
  ON t1
  FOR EACH ROW
DECLARE
...

答案 1 :(得分:1)

如果您有11g,则可以使用Flashback Data Archive来执行此操作,

答案 2 :(得分:0)

实际上,如果您知道所需数据的时间,则可以恢复旧数据,而无需使用以下查询创建日志表。它可能满足您的要求。

SELECT * FROM TABLE_NAME AS OF TIMESTAMP

(提供所需记录作为时间戳的时间)

答案 3 :(得分:0)

这是我在项目中使用的一些PL / SQL,可以完全按照你想要的那样做。

我简化了我的脚本(它正在做一些其他功能):

create or replace trigger rtt.course_log
       after insert or update or delete
       on rtt.TRAINING_COURSE
       for each row

declare msg varchar2(255);

begin
        if updating then
           msg := 'updating course: ' ||  :new.name || 'at: ' || :new.updated_at;
        elsif inserting then
           msg := 'creating course: ' ||  :new.name || 'at: ' || :new.updated_at;
        elsif deleting then
           msg := 'deleting course: ' ||  :new.name || 'at: ' || :new.updated_at;
        end if;
        insert into rtt.TRAINING_LOG (message, created_at) values (msg, SYSDATE);
end;