在更新前将行复制到历史记录表,而不在PL/SQL触发器中枚举列名



我正在尝试创建一个PL/SQL触发器,该触发器在更新行时将行的当前版本复制到历史表中。这样做很容易:

CREATE OR REPLACE TRIGGER foo BEFORE UPDATE ON bar FOR EACH ROW
BEGIN
  INSERT INTO bar_history VALUES bar.id = :old.id, bar.col1 = :old.col1 /* ...and so on */;
END;

但是,我希望避免枚举所有列名,因为表barbar_history是相同的,并且我不想每次更改表时都更新触发器。我尝试了两种方法,但都不起作用。有其他办法解决这个问题吗?

方法1:

CREATE OR REPLACE TRIGGER foo BEFORE UPDATE ON bar FOR EACH ROW
BEGIN
  INSERT INTO bar_history VALUES :old;
END;

由于您显然不能将:old用作行类型(请参阅此问题),我收到以下错误消息:

PLS-00049:绑定变量"OLD"错误

方法2:

CREATE TRIGGER foo BEFORE UPDATE ON bar FOR EACH ROW
BEGIN
  INSERT INTO bar_history
  SELECT * FROM bar WHERE id = :old.id;
END;

这也给了我一个错误:

ORA-04091:BAR正在发生变化,触发器/功能可能看不到

您需要引用各个列。无法引用触发器中的整行。如果许多表需要这样做,或者表定义经常更改,则可以基于数据字典视图编写pl/sql来为您生成触发器。更新:这里有类似的问题/答案:在Oracle触发器中,我可以为行类型变量分配新的和旧的吗?

有些人以前遇到过这种情况。他们的方法是使用包全局变量来存储rowid,并在after语句触发器中动态选择列名。https://community.oracle.com/message/370167

Tom Kyte对此也有一些建议

https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:734825535375https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:59412348055

在这种情况下,您可以使用列表分区策略(一种用于当前C和历史H)创建分区表。您可以创建而不是触发,在更新表的情况下,将插入记录,并将现有记录状态更新为H,这将隐式地将记录移动到历史分区。

相关内容

  • 没有找到相关文章

最新更新