2013-12-12 32 views
1

我試圖使用all_tab_columns將大型觸發器代碼簡化爲簡潔的代碼,因爲表中包含200列。使用動態sql嘗試時有一些原因,它不會讓我更新聲明的變量。使用Trigger的Oracle動態sql使用:new和:old變量

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; 
/

任何建議???

回答

2

你不能這麼做:變量new和old在動態SQL中超出範圍。

你也不能這樣做rowtype/Oracle類型 - 我嘗試了很多次不同的事情。

你可以做的 - 動態生成完整的觸發代碼。我這樣做的觸發器,它將所有的東西重新加載到表格數據變化的歷史表格上。

而至於你觸發的體積非常大(如果它的長度超過了32767個字節),你應該使用DBMS_SQL包,而不是執行即時

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會那麼就可能傳遞給您的存儲過程的對象類型的實際情況申報表格。

相關問題