Oracle PL / SQL: Colonne ciclo su trigger dinamicamente
-
16-09-2019 - |
Domanda
All'interno di un trigger che sto cercando di loop su tutte le colonne su un tavolo e confrontare i nuovi valori per i vecchi valori. Ecco quello che ho finora:
CREATE OR REPLACE TRIGGER "JOSH".TEST#UPD BEFORE
UPDATE ON "JOSH"."TEST_TRIGGER_TABLE" REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW
declare
oldval varchar(2000);
newval varchar(2000);
begin
for row in (SELECT column_name from user_tab_columns where table_name='TEST_TRIGGER_TABLE') loop
execute immediate 'select :old.'||row.column_name||' from dual' into oldval;
execute immediate 'select :new.'||row.column_name||' from dual' into newval;
--Do something here with the old and new values
end loop;
end;
Il grilletto compila, ma quando i fuochi di innesco, sto ottenendo:
ORA-01008: non tutte le variabili legate
sulla prima esecuzione immediata, perché è in attesa di un valore per :old
. :old
e :new
sono già definiti come parte del grilletto, ma sembra che eseguire immediato non può vedere quelle variabili.
C'è un modo per scorrere in modo dinamico nel corso dei valori delle colonne in un trigger?
Soluzione
No, non è possibile fare riferimento: vecchi e nuovi: i valori in modo dinamico. Come suggerisce Shane, è possibile scrivere codice per generare il codice di attivazione statica, se questo ha la vita più facile. Inoltre, è possibile rendere "fare qualcosa qui" in una procedura pacchetto in modo che il trigger diventa:
CREATE OR REPLACE TRIGGER JOSH.TEST#UPD BEFORE
UPDATE ON JOSH.TEST_TRIGGER_TABLE
begin
my_package.do_something_with (:old.col1, :new.col1);
my_package.do_something_with (:old.col2, :new.col2);
my_package.do_something_with (:old.col3, :new.col3);
-- etc.
end;
(Si può abbandonare la clausola REFERENCING inutile tra l'altro).
Altri suggerimenti
Non sono sicuro se si può fare ciò che si sta cercando di fare. Qual è la ragione per cui non si vuole nominare esplicitamente le colonne della tabella all'interno del codice PL / SQL? Se i campi della tabella stanno cambiando spesso, si potrebbe costruire PL / SQL che costruisce in modo dinamico il trigger PL / SQL per ogni tabella (con i nomi dei campi esplicite in ciascuna). Ogni volta che cambia la tabella, è possibile eseguire che PL / SQL per generare il nuovo trigger.
Stai essenzialmente cercando di costruire il proprio sistema di verificare tutte le modifiche alla tabella? (La mia ipotesi migliore su cosa si potrebbe fare con i vecchi e nuovi valori delle colonne arbitrari.) Se è così, si potrebbe voler esaminare proprie capacità di controllo di Oracle.
Ho avuto un problema simile, anche se in MSSQL.
La mia soluzione era di scrivere una stored procedure che consente di scorrere le tabelle e colonne informazioni (tramite viste del dizionario o un repository personalizzato) e genera i trigger necessari. La procedura deve essere eseguito solo se il modello di dati cambia.
Il vantaggio è che non c'è bisogno di scorrere gli metamodello in ogni aggiornamento, ma piuttosto di generare i trigger in anticipo.