0

我知道,这个问题已经被构思了很多次了,但我需要你的建议 :)

有2张桌子:

  • 销售收入

| item |income |create_user |create_date |last_update_user | update_time| |------|-------|------------|-------------------|-----------------|------------| | 1 | 100 |duck |05-19-2016 |human |05-19-2016 | | 2 | 250 |dog |05-19-2016 |human |05-19-2016 | | 3 | 210 |cat |05-20-2016 |human |05-19-2016 |

  • 销售收入审计

| item |change_id|last_inc|new_inc |user_update|update_date|operation | |------|---------|--------|----------|-----------|-----------|------------| | 1 | 1 |null |05-19-2016|duck |05-19-2016 |I | | 2 | 2 |null |05-19-2016|dog |05-19-2016 |I | | 3 | 33 |null |05-20-2016|cat |05-19-2016 |I |

任务是:当有人执行插入、更新或删除操作时,触发器必须将上面发生操作的记录插入到表Sale_income_audit中(操作类型 - 列“操作”)。同时必须更新表 Sale_income(last_update_user 和 update_time)。我这样做了:使用 3 个变量创建包:

create or replace package Sale_income_var as
    v_old_income BINARY_INTEGER := null;
    v_new_income BINARY_INTEGER := null;
     v_item      BINARY_INTEGER := null;
END Sale_income_var;

和 2 个触发器

第一的

create or replace trigger audit_income_IUD
  after insert or update or delete on Sale_income
    for each row
begin  
    .
    .                
elsif updating then  
        Sale_income_var.v_old_income  := :old.income;
        Sale_income_var.v_new_income  := :new.income;                     
             if  Sale_income_var.v_item is null then                      
        Sale_income_var.v_item := :old.item;
        DBMS_OUTPUT.PUT_LINE(Sale_income_var.v_item);
            end if;
     .
     .
end if;
end audit_income_IUD;

第二

create or replace trigger  sale_income_au
  after update of income on Sale_income
 begin 
   update Sale_income set last_update_user = user, last_update_date = sysdate
       where item = Sale_income_var.v_item;     
   INSERT into Sale_income_audit   (item, 
                                  change_id, 
                                  last_income, 
                                  new_income, 
                                  user_update, 
                                  update_date, 
                                  operation)
                             VALUES (Sale_income_var.v_item,
                                     auto_incr.NEXTVAL, 
                                     Sale_income_var.v_old_income, 
                                     Sale_income_var.v_new_income,
                                     user,
                                     sysdate,
                                     'U');                         
             Sale_income_var.v_item := null;
    end sale_income_au;

它有效,但我认为这是错误的解决方案。因为从“一般”触发器更新块移动到另一个触发器,这个带有变量的魔法不好,我是对的吗?

您将如何决定这项任务以及您将在我的解决方案中进行哪些更改?感谢帮助 :)

4

2 回答 2

1

只需一个BEFORE触发器即可完成。
before触发器允许修改表列的NEW值,而这些修改后的值存储在表中,因此last_update_user可以update_time通过这种方式更新列。

create or replace trigger audit_income_IUD
BEFORE insert or update or delete on Sale_income
    for each row
declare
      operation_type char;
begin 

  if updating or inserting then
         :new.update_time := sysdate;
         :new.last_update_user := user;
  end if;

  CASE 
       WHEN updating THEN operation_type := 'U';
       WHEN inserting THEN operation_type := 'I';
       WHEN deleting THEN operation_type := 'D';
  END CASE;

  INSERT into Sale_income_audit   (item, 
                                  change_id, 
                                  last_income, 
                                  new_income, 
                                  user_update, 
                                  update_date, 
                                  operation)
                       VALUES (:old.item,
                                  auto_incr.NEXTVAL, 
                                  :old.income, 
                                  :new.income,
                                  user,
                                  sysdate,
                                  operation_type);     
end;
/
于 2016-05-22T05:06:08.083 回答
0

答案似乎很简单。需要每行之后使用并添加块“更新”

    :new.last_update_user := user;
    :new.last_update_date := sysdate;

并且我们可以限制为一个没有包装的触发器!

于 2016-05-21T21:27:20.927 回答