带触发器的Oracle动态sql使用:new和:old变量

带触发器的Oracle动态sql使用:new和:old变量,oracle,plsql,Oracle,Plsql,我试图使用所有的_tab_列将大型触发器代码简化为简洁的代码,因为该表包含200列。由于某些原因,当尝试使用动态sql时,它不允许我更新声明的变量 DECLARE v_new_rec SOME_TABLE%ROWTYPE; v_sql VARCHAR(4000); BEGIN SELECT 'v_new_act.' || lower(column_name) || ' := :new.' || lower(column_name) INTO v_sql FROM all_t

我试图使用所有的_tab_列将大型触发器代码简化为简洁的代码,因为该表包含200列。由于某些原因,当尝试使用动态sql时,它不允许我更新声明的变量

DECLARE
v_new_rec SOME_TABLE%ROWTYPE;
v_sql VARCHAR(4000);
BEGIN

  SELECT 'v_new_act.' || lower(column_name) || ' := :new.' || lower(column_name)
    INTO v_sql
    FROM all_tab_columns
   WHERE table_name = 'SOME_TABLE'
ORDER BY column_id;

EXECUTE IMMEDIATE v_sql USING v_new_rec;

EXEC my_stored_proc(v_new_rec);

END;
/

有什么建议吗

您不能这样做:变量:new和:old超出了动态SQL的范围

您不能同时以rowtype/Oracle类型执行此操作-我用不同的方法尝试了很多次

您所能做的就是动态生成完整的触发器代码。我这样做是为了触发器在表数据更改时将所有内容重新加载到历史记录表


如果触发器的大小非常大(如果长度超过32767字节),则应该使用dbms_sql包,而不是执行立即的

您不能这样做:变量:new和:old超出了动态sql的范围

您不能同时以rowtype/Oracle类型执行此操作-我用不同的方法尝试了很多次

您所能做的就是动态生成完整的触发器代码。我这样做是为了触发器在表数据更改时将所有内容重新加载到历史记录表


如果触发器的大小非常大(如果长度超过32767字节),则应该使用dbms_sql包,而不是立即执行

这种方法不起作用,也不可能起作用。您不能动态引用
:new
:old
伪记录

如果您想沿着这条路走下去,实际上您需要编写生成触发器的动态SQL,而不是触发器中的动态SQL。类似(显然未经测试)的东西


或者,如果要基于对象类型声明表,
:new
:old
将是对象类型的实际实例,然后可以传递给存储过程。

这种方法不起作用,也不可能起作用。您不能动态引用
:new
:old
伪记录

如果您想沿着这条路走下去,实际上您需要编写生成触发器的动态SQL,而不是触发器中的动态SQL。类似(显然未经测试)的东西

或者,如果要基于对象类型声明表,
:new
:old
将是对象类型的实际实例,然后可以传递给存储过程

l_sql := 'CREATE OR REPLACE TRIGGER trg_' || l_table_name ||
         '  BEFORE INSERT ON ' || l_table_name ||
         '  FOR EACH ROW ' ||
         'DECLARE ' ||
         '  l_rec ' || l_table_name || '%ROWTYPE' ||
         'BEGIN ';
for cols in (select * from all_tab_cols where table_name = l_table_name)
loop
  l_sql := l_sql || ' l_rec.' || cols.column_name || 
                       ' = :new.' || cols.column_name || ';';
end loop;
...