在 Oracle 触发器中,我可以将 new 和 old 分配给 rowtype 变量吗?

Joh*_*n O 4 oracle triggers

我的任务是实现几个触发器脚本,并且我从同事那里得到了可供参考的示例。在这些中,他们使用 pl-sql 条件进行更新/插入/删除,以及巨大的插入语句(在另一个表中)。这些插入语句除了值是否以新前缀或旧前缀之外没有任何变化。我想我会很聪明,并尝试使用以下内容使我的变得更紧凑:

DECLARE
  vRow SATURN.SPRCMNT%ROWTYPE;

BEGIN

  IF UPDATING THEN
    vRow := :NEW;
  ELSIF INSERTING THEN
    vRow := :NEW;
  ELSIF DELETING THEN
    vRow := :OLD;
  END IF;

  -- Not the real insert statement
  INSERT INTO blah 
    (columns)
    VALUES
    (vRow.somecolumns);

END;
Run Code Online (Sandbox Code Playgroud)

我从编译系统得到以下信息:

10/13  PLS-00049: bad bind variable 'NEW'
13/13  PLS-00049: bad bind variable 'NEW'
16/13  PLS-00049: bad bind variable 'OLD'
Run Code Online (Sandbox Code Playgroud)

显然它不喜欢这样。有什么可以实现我正在尝试的吗?:new 和 :old 不是真正的行类型吗?将本质上相同的代码重复 3 次似乎很愚蠢,但我想不出更好的方法。天哪,我想我读到触发器的大小也有一些硬性限制。任何帮助表示赞赏。

[编辑] 只是一个想法,是否可以在 DECODE() 中以某种方式引用 UPDATING/INSERTING 关键字?

例如,如果我可以执行 DECODE(SOMETHINGVAR, UPDATING, :NEW.column, DELETING, :OLD.column),那么我可以使用单个语句设置 vRow 中每列的值。

我想最好先检查“删除”,然后使用其他两个的默认值。

这可能吗?

Rus*_*sty 5

我决定回答这个问题,因为我已经听过很多次了,但从未见过任何解决方案。

因此,我们的想法是拥有一个通用的“结构独立”触发器,调用某个传递整个新行和旧行的 PL/SQL 过程。

我为此使用了对象表。

create or replace type test_table_type as object(
  ... your attributes ....
);

create table test of test_table_type;

create or replace trigger trg_test_upd
before update on test
for each row
  l_new_row  test_table_type;
  l_old_row  test_table_type;
  l_row_id   raw(40000);
begin
  l_new_row := :new.sys_nc_rowinfo$; -- <-- this is your new row
  l_old_row := :old.sys_nc_rowinfo$; -- <-- this is your old row
  l_row_id :=  :old.sys_nc_oid$; -- <-- this your row logical ID (not rowid!!!). You can use it if you don't have primary key or it is composite.
  -- here you can do what ever you want with you old/new rows.
  ...
end;
/
Run Code Online (Sandbox Code Playgroud)

我喜欢这种方法,因为它允许在基本类型中定义公共属性并从此类型继承其他类型。因此,即使对于基于相同基本类型的许多表,您也可以使用通用代码。