Newsgroup: it.comp.software.database
Titolo: Trigger in postgres

Salve, vi spiego la mia necessità: all'inserimento di un nuovo record
nella tab anag1 dovrei verificare se questo esiste nella tab anag2,
tramite il campo cod_fiscale o p_iva, e se esiste eliminarlo nella tab
anag2.
Invece che farlo da codice php, avevo pensato di fare un trigger
sull'insert di anag1 ed utilizzare un delete sulla tab anag2.
Il porblema è che non ho mai utilizzato i trigger, quindi se qualcuno
potesse aiutarmi!?!?
Ho letto qualcosa a riguardo e penso che dovrei fare una cosa del
genere:
CREATE TRIGGER verifica_anagrafica
AFTER INSERT ON anag1
BEGIN
     DELETE FROM anag2 WHERE cod_fiscale = (... qui non so cosa
mettere!!!!) or p_iva = (... qui non so cosa mettere!!!!)
END
' LANGUAGE plpgsql;
Se qualcuno può aiutarmi...
Thanks

 anag2.
CREATE OR REPLACE FUNCTION chk_tab2() RETURNS TRIGGER AS $xx$
BEGIN
    DELETE FROM anag2 WHERE cod_fiscale = NEW.cod_fiscale OR
        p_iva = NEW.p_iva;
RETURN NEW;
END;
$xx$ language 'plpgsql';
DROP TRIGGER IF EXISTS chk_tab2 ON anag1;
CREATE TRIGGER chk_tab2 BEFORE INSERT OR UPDATE ON anag1
    FOR EACH ROW EXECUTE PROCEDURE chk_tab2();
ciao ...
-- 
Never try to teach a pig to sing.
It wastes your time and annoys the pig.

     FOR EACH ROW EXECUTE PROCEDURE chk_tab2();
Ti ringrazio tantissimo, ho appena finito di fare dei controlli e
sembra che funzioni alla grande!
Ho dovuto solo fare dei piccoli "aggiustamenti", per il resto tutto
ok.
Grazie ancora per l'aiuto

 wrote:
ricordati solo che nei trigger su INSERT hai solo NEW.<campi>, su UPDATE hai
OLD.<campi> e NEW.<campi> e su DELETE hai solo OLD.<campi> ..
http://www.postgresql.org/docs/8.3/static/plpgsql-trigger.html
e per un debug "grezzo" puoi usare RAISE NOTICE (che non ti interrompe la
funzione) o RAISE EXCEPTION che te la interrompe ... ad es:
    ...
    RAISE NOTICE 'in questo punto codice vale %', NEW.codice;
    ...
il resto e' prove, debug e "aggiustamenti" ;-))


Un'ultima richiesta: e se io volessi copiare il record da eliminare in
un'altra tabella, tanto per avere un resoconto di tutti i record
cancellati?
E' possibile? Come faccio ad ottenere i valori da inserire?
Tipo una cosa del genere:
CREATE OR REPLACE FUNCTION chk_tab2() RETURNS TRIGGER AS $xx$
BEGIN
    INSERT INTO anag_eliminati(id, cognome, p_iva, etc.)
VALUES(?,?,?,?,...);
    DELETE FROM anag2 WHERE cod_fiscale = NEW.cod_fiscale OR
        p_iva = NEW.p_iva;
RETURN NEW;
END;
$xx$language'plpgsql';
Thanks

 E' possibile? Come faccio ad ottenere i valori da inserire?
CREATE OR REPLACE FUNCTION chk_tab2() RETURNS TRIGGER AS $xx$
DECLARE
    my_row anag2%ROWTYPE;
BEGIN
    SELECT * INTO my_row FROM anag2 WHERE cod_fiscale = NEW.cod_fiscale
        OR p_iva = NEW.p_iva;
    IF FOUND THEN
        INSERT INTO anag_eliminati(id, cognome, p_iva, etc.)
            VALUES (
my_row.id
, my_row.cognome, my_row.p_iva, etc. ..);
        DELETE FROM anag2 WHERE cod_fiscale = NEW.cod_fiscale OR
            p_iva = NEW.p_iva;
    ENDIF;
    RETURN NEW;
END;
$xx$language'plpgsql';
da controllare !!


             p_iva = NEW.p_iva;
ancora meglio, se hai un id univoco:
         DELETE FROM anag2 WHERE id = 
my_row.id
;


 E' possibile? 
Si. Quello che vuoi si chiama auditing dei dati. In poche parole, si
posiziona un trigger BEFORE INSERT OR DELETE OR UPDATE sulla tabella che
ti interessa mantenere in audit, dopodiche`, in caso di modifica del
record, si provvedera` a copiare i valori  su di un'altra tabella
(la cui struttura sara` speculare a quella della tabella orginale, con
l'aggiunta di alcuni campi di controllo). Un esempio di questa tecnica
lo trovi 
http://www.postgresql.org/docs/8.3/static/plpgsql-trigger.html
Enrico
P.S. alla pagina riportata, viene usato un metodo un po' spicciolo per
inserire i dati nella tabella di audit. Personalmente, preferisco
chiamare una INSERT classica, e specificare campo per campo
nell'istruzione. Inoltre, ma qui varia da una scuola di pensiero
all'altra, in fase di UPDATE dei dati, personalmente preferisco inserire
nella tabella di audit prima il vecchio valore e poi il nuovo

Grazie per i suggerimenti: sono stati veramente di grande aiuto!
Sto testando l'applicazione e sembra che funzioni tutto perfettamente.
Spero che questa discussione sia di utilità anche ad altri.
Grazie ancora per il prezioso supporto.
Thanks