我正在尝试使用all_tab_columns将大型触发器代码简化为简洁代码,因为表包含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;
/
任何建议???
答案 0 :(得分:3)
这种方法不起作用,也不起作用。您无法动态引用:new
或:old
伪记录。
如果您想沿着这条路走下去,您实际上想要编写生成触发器的动态SQL,而不是触发器中的动态SQL。有些东西(显然是未经测试的)
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;
...
或者,如果要根据对象类型声明表,:new
和:old
将是对象类型的实际实例,然后可以将其传递给存储过程。
答案 1 :(得分:2)
你不能这样做:变量:new和:old超出了动态SQL的范围。
你也不能把它作为rowtype / Oracle类型 - 我尝试过多次不同的事情。
您可以做的一切 - 动态生成完整的触发器代码。我是为触发器做的,它将所有的东西重新加载到表数据更改的历史表中。
就你的触发器的大小而言(如果它的长度超过32767字节)你应该使用dbms_sql包而不是立即执行