在表上创建复杂的触发器

时间:2012-07-18 20:34:16

标签: oracle triggers plsql oracle11g

我有一个表参与者,其结构如下所示:

Pid    number        
name   varchar2(20)    
version  number

每当我在participants表格中插入任何记录时,都会填充版本= 1

例如,如果我插入了pid = 1,则name ='Gaurav'然后记录version =1,请填入participants table

现在我的issue位于update表{/ 1}}上,

  1. 假设我在参与者表中为pid = 1更新name ='Niharika',然后需要在同一个表上创建一个pid = 1,name ='Niharika'和version = 2的新记录。
  2. 我再次在参与者表格中为pid ='1'更新name ='Rohan',需要创建一个pid = 1,name ='Rohan'且版本= 3的新记录。
  3. 我怎样才能实现这一点,清楚地说,我需要为将要更新的pid获得最大(版本)+1。

    我可以使用视图实现这一点并使用而不是触发器插入到视图中,但我对我的解决方案不满意。

    我也创建了复合触发器,即使这对我不起作用,因为在触发器中我需要对该表使用insert语句,这会给我递归错误

2 个答案:

答案 0 :(得分:2)

你应该有两张桌子。使用您描述为“日志记录”表的结构制作一个。它将保留所有记录的历史记录。有另一个被认为是“当前”的表,但是没有version列。然后,当在“当前”表的记录上发生插入/更新时,在日志记录表中有一个机制(例如,触发器)SELECT FOR UPDATE max(版本),添加一个,并插入到日志记录表中。这样,你就不会遇到变异表错误或类似的奇怪事情。这种方式有一些序列化,但它最接近你想要做的事情。

答案 1 :(得分:-1)

通常不推荐,但无论如何都没有其他额外的记录表,无论如何都可以这样做 -

CREATE or REPLACE
TRIGGER part_upd
 AFTER UPDATE of name
 ON participants
 FOR EACH ROW
DECLARE
  retval BOOLEAN;
BEGIN

   retval := insert_row(:old.pid,:new.name);

END part_upd;

功能 -

CREATE or REPLACE 
FUNCTION insert_row (pid1 number, name1 varchar2)
RETURN boolean
IS
    PRAGMA autonomous_transaction;
BEGIN
     INSERT INTO participants
     SELECT pid1, name1, max(vers)+1
       FROM participants
      WHERE pid = pid1;         

     COMMIT; 

     RETURN true;
END;

您必须通过添加日志记录和异常处理来正确微调触发器和功能。详细了解autonomous_transaction