Newsgroup: it.comp.software.database
Titolo: Oracle trigger

Salve a tutti.
Vorrei che ogni volta che si inserisce un record in una tabella IN_MESSAGE
venga scatenato un trigger il quale a sua volta chiami una procedura,
passandole i valori di alcuni campi appena inseriti.
Il trigger e' stato definito cosi':
create or replace trigger processnewmessage
after  insert on IN_MESSAGE
for each row
call procedure_name(:new.CODE, :new.BODY)
/
la procedura in questo caso non fa una benemerita cippa ...
Il tutto funziona se invece di quei :new.CODE, :new:BODY passo un numero e
una stringa.
Ad esempio:
call procedure_name(1, 'Babbeo che sono")
Qualcuno mi sa aiutare?

Mentre cercavo di capire la differenza tra una select e un drop database,
Tom Cat ha osato scrivere:

ciao. Ho provato a replicare la tua situazione e tutto mi funziona
regolarmente:
SQL> create table da_rimuovere (code int, text char(4));
Table created.
Ho creato un procedura stupidissima che mostra l'echo dei parametri
passati:
SQL>create procedure proc_da_rimuovere (numero int, testo char) is
    2 begin
    3 DBMS_OUTPUT.PUT_LINE (numero||testo);
    4 end proc_da_rimuovere;
Procedure created.
SQL>create trigger trg_da_rimuovere
    2 after insert on DA_RIMUOVERE
    3 for each row
    4 call proc_da_rimuovere(:new.code, :new.text)
    5 /
Trigger created.
la procedura funziona:
SQL> set serveroutput on
SQL> begin
  2  proc_da_rimuovere(4,'bye');
  3  end;
  4  /
4bye
PL/SQL procedure successfully completed.
anche il trigger funziona correttamente, infatti chiama la procedura che
mostra correttamente i dati inseriti:
SQL> insert into da_rimuovere values (23,'helo');
23helo
1 row created.
Prova fare altrettanto: creati la stupidissima procedura che fa l'echo
dei parametri che gli vengono passati e vedi cosa succede.
ciao

Cazzarola ... ho capito perche' non funziona.
In realta' la procedura invoca codice esterno che fa una select sulla riga
appena inserita la quale, non essendo ancora committata, fallisce. A questo
punto mi chiedo: è possibile far si che il trigger scatti al commit della
riga?

 Cazzarola ... ho capito perche' non funziona. In realta' la procedura

quindi ricevi l'errore ORA-04091??  se e' cosi' allora
auguri.....scherzo  :-)  ci sono alcuni workaround su metalink,
dovresti vedere se vanno bene per il tuo caso.
ciao.

 ha scritto nel messaggio
news:o5Zba.8652$Fc.2...@tornado.fastwebnet.it...



Ho risolto il problema facendo scatenare il trigger non sulla insert, ma su
una update "fake" della riga appena inserita.
Quindi:
(1) insert into bla bla
(2) commit;
(3) update "fake" che scatena il trigger; il codice esterno ora puo'
eseguire la select sul database visto che l'insert e' stata committata.
----
A questo punto mi sorge il seguente dubbio esistenziale sui trigger ...
mettiamo di avere 2 tabelle (chiamiamole "uffici" e "impiegati"); supponiamo
di aver anche impostato un trigger sulla tabella uffici che in seguito alla
cancellazione di un ufficio, cancelli anche gli impiegati di quello stesso
ufficio.
Visto che il corpo del trigger "autocommitta", in seguito ad una rollback
sulla delete dell'ufficio mi ritroverei con l'ufficio senza utenti.
Se questo mio ragionamento e' corretto, allora in che occasioni e'
consigliato l'uso dei trigger?


Il problema e' proprio quello ... il trigger che chiama la procedura, scatta
sulla insert, non sulla commit. Mi sembra di aver capito che l'unico modo
per risolvere tale questione e' di usare workaround come quello che ho
postato poco sopra (insert -> commit -> update "fake" che fa scattare il
trigger).
Ciao e grazie.

...

Puoi fare una materialized view, fast refresh on commit, ed inserire
il trigger sulla materialized
Greetings,
Alessandro Trebbi
Pesaro, Italy
http://www.b3soft.com

 e' consigliato l'uso dei trigger?
 
Occhio !! non e' esattamente cosi':il trigger non ''autocommitta'' da solo.
Il trigger viene acceso (fired come dice Oracle) dalla transazione che
esegue l'operazione sulla tabella e resta facente parte di quella
transazione. Se una qualunque operazione delegata al trigger non va a
buon fine TUTTA la transazione iniziale fara' roll-back.
E ovviamente se fai roll-back della transazione anche le operazioni
eseguite dal trigger farranno roll-back! (e ci mancherebbe altro che
non fosse cosi'!)
esempio:
SQL>create table da_rimuovere_bis as select * from da_rimuovere where 1=2;
Table created.
SQL> create or replace trigger trg_da_rimuovere
    2 after insert on DA_RIMUOVERE
    3 for each row
    4 begin
    5 insert into da_rimuovere_bis (code, text) values (:new.code, :new.text);
    6 end;
    7 /
Trigger created.
SQL> select * from da_rimuovere;
      CODE TEXT
---------- ----
        11 aaaa
        22 bbbb
SQL> select * from da_rimuovere_bis;
no rows selected
SQL> insert into da_rimuovere values (33,'cccc');
1 row created.
SQL> select * from da_rimuovere;
      CODE TEXT
---------- ----
        33 cccc
        11 aaaa
        22 bbbb
SQL>  select * from da_rimuovere_bis;
      CODE TEXT
---------- ----
        33 cccc
SQL> rollback
  2  ;
Rollback complete.
SQL>  select * from da_rimuovere;
      CODE TEXT
---------- ----
        11 aaaa
        22 bbbb
SQL> select * from da_rimuovere_bis;
no rows selected
Scusa se ti costringo a leggere degli esempi:
credo sia il miglior modo di spiegarsi.
ciao

 credo sia il miglior modo di spiegarsi.
La spiegazione ad esempi e' perfetta, ci mancherebbe altro ...
Un giorno per sdebitarmi ti spieghero' la differenza tra select e drop
database ;-)))))
Ciao


A questo punto mi sa che abbandono la strada trigger e risolvo la questione
interamente pure-Java (e' inutile ammazzare una formica con un esercito
...); pensavo che i trigger mi avrebbero semplificato la vita, invece me
l'hanno complicata :-). Comunque, a scopo didattico, appena avro' un attimo
di tempo provero' anche la soluzione che mi suggerisci tu.
Grazie
Tom Cat

 Ciao
LOL ;-)

 buon fine TUTTA la transazione iniziale fara' roll-back.
E' anche possibile fare dei triggers indipendenti dalla transazione,
inserendo PRAGMA AUTONOMOUS_TRANSACTION ,
e poi committando separatamente alla fine del trigger (utile ad
esempio per loggare degli errori)
