oracle和创造历史

时间:2010-08-09 17:42:27

标签: oracle

我正在研究一个跟踪项目历史的系统。有3个主表:项目,任务和客户端,然后是每个3个历史表。我在项目表上有以下触发器。

 CREATE OR REPLACE TRIGGER mySchema.trg_projectHistory
 BEFORE UPDATE OR DELETE
 ON mySchema.projects REFERENCING NEW AS New OLD AS Old
 FOR EACH ROW
 declare tmpVersion number;
 BEGIN
  select myPackage.GETPROJECTVERSION( :OLD.project_ID ) into tmpVersion from dual;

  INSERT INTO mySchema.projectHistiry
    ( project_ID, ..., version )
  VALUES
    ( :OLD.project_ID,
    ...
     tmpVersion
     );

EXCEPTION
 WHEN OTHERS THEN
   -- Consider logging the error and then re-raise
   RAISE;
END ;
/

我的每个表(项目,任务,客户)都有三个触发器。

这是挑战:并非一切都在同一时间发生变化。例如,某人可能只是更新某个任务的成本。在这种情况下,只有一个触发器触发,我有一个插入。即使项目和客户表中没有任何变化,我也希望一次将一条记录插入3个历史表中。

此外,如果有人更改项目的end_date,成本,并说选择另一个客户端,该怎么办?现在,我有三个同时触发的触发器。只有在这种情况下,我才会在我的三个历史表中插入一条记录。 (我想要的)

如果我修改触发器以插入到第一个示例的3个表中,那么当第二个示例发生时我将有9个插入。

不太确定如何解决这个问题。任何帮助?

3 个答案:

答案 0 :(得分:2)

对我来说,这听起来好像你想要对这些表中的任何一个表进行更改时创建的三个表的事务级快照。

在三个表中的每个表上都有一个行级触发器,它使用项目ID和可选的客户端/任务ID调用单个打包过程。

打包过程在所有三个历史表中插入相关项目,客户端和任务,其中没有该键和事务的历史记录(即您不需要重复项)。对于后者,你有几个选择。您可以使用唯一约束,BULK选择和插入FORALL / SAVE EXCEPTIONS,DML错误记录(EXCEPTIONS INTO)或INSERT ... SELECT ... WHERE NOT EXISTS ...

您需要跟踪您的交易。我猜这是你用myPackage.GETPROJECTVERSION做的。这里的诀窍是只在你有新事务时增加版本。如果在获得新版本号时,将其保存在pacakge级别变量中,则可以轻松判断您的会话是否已获得版本号。

如果您的会话将要运行多个事务,那么如果它是先前事务的一部分,您将需要“清除”会话级版本号。如果您获得DBMS_TRANSACTION.LOCAL_TRANSACTION_ID并将其存储在包/会话级别,则可以确定您是在新事务中还是在同一事务中。

答案 1 :(得分:0)

根据您的描述,看起来您会在任何原始行更改后捕获每个历史记录行的有效日期和结束日期。

EG。 Project_hist表将包含eff_date和exp_date,它具有给定项目的开始和结束日期。项目表只有一个生效日期。 (因为它是活跃的项目)。

当只更新其中一个表值时,我不明白为什么要为所有三个历史记录表插入行。您可以使用当前逻辑,根据需要(截至给定日期)获取详细信息。 (在历史表中为仅已更新的表插入旧行。)。

答案 2 :(得分:0)

替代答案。 看看Total Recall / Flashback Archive 您可以将保留期设置为10年,并使用简单的AS OF TIMESTAMP来获取任何特定时间戳的数据。

不确定性能。可能更容易进行每日或每周保留,然后使用VERSIONS BETWEEN语法选择旧版本的单独计划作业,并将其存储在历史记录表中。