[T-SQL] Trigger

giovedì 18 gennaio 2007 - 14.36

walteradrian Profilo | Newbie

Ciao a tutti è il primo post che vi scrivo anche se vi leggo da molto tempo.

Vi spiego il mio problema: devo portare un DB fatto in PostgreSQL in T-SQL, e ho un problema con i Trigger.
Nel caso specifico devo creare un trigger che comprende tutte e 3 le operazioni(Insert, Update, Delete) ma non trovo il modo per riconoscere l'operazione che scatena il trigger.

In PostgreSQL esiste l'operatore TG_OP che riconosce l'operazione, quindi basta scrivere IF (TG_OP = 'DELETE') THEN, IF (TG_OP = 'INSERT') THEN etc etc...

Ma in T-SQL non esiste questo operatore!!!!

Vi ringrazio anticipatamente

Brainkiller Profilo | Guru

>Ciao a tutti è il primo post che vi scrivo anche se vi leggo
>da molto tempo.

Ciao Benvenuto.

>In PostgreSQL esiste l'operatore TG_OP che riconosce l'operazione,
>quindi basta scrivere IF (TG_OP = 'DELETE') THEN, IF (TG_OP =
>'INSERT') THEN etc etc...

Rispondo io anche se Lorenzo sarà sicuramente più preciso.

Una soluzione è creare 3 Triggers invece di 1. Uno per Delete, uno per Insert e uno per Update e definire lì dentro la logica dei tre eventi.

L'altra soluzione è lavorare sulle tabelle "virtuali" inserted e deleted che contengono appunto i records inseriti o eliminati nell'operazione che ha fatto scattare il trigger. Puoi lavorarci come se fossero tabelle vere e proprie es. Select count(*) from inserted ecc.

In questo caso:

- se nella inserted hai un numero di righe maggiore di 0 e nella deleted hai zero records, trattasi di una INSERT
- se nella inserted hai 0 e nella deleted hai un numero maggiore di zero, è una DELETE
- se nella inserted hai un numero maggiore di zero, e così anche nella deleted, è un UPDATE.

Quindi su queste condizioni fai degli IF e inserisci la logica, tutta in un solo Trigger.
Non so se in SQL 2005 hanno provveduto mettendo una keyword tipo Postgres.
Ciao

David De Giacomi | Microsoft MVP
http://blogs.dotnethell.it/david/

lbenaglia Profilo | Guru

>Nel caso specifico devo creare un trigger che comprende tutte
>e 3 le operazioni(Insert, Update, Delete) ma non trovo il modo
>per riconoscere l'operazione che scatena il trigger.
>
>In PostgreSQL esiste l'operatore TG_OP che riconosce l'operazione,
>quindi basta scrivere IF (TG_OP = 'DELETE') THEN, IF (TG_OP =
>'INSERT') THEN etc etc...

Ciao walteradrian,

carino PostgreSQL
SQL Server è "meno evoluto" ma puoi testare in cascata il numero di righe contenute nelle tabella virtuali INSERTED e DELETED:

IF (SELECT COUNT(*) FROM INSERTED) > 0 AND (SELECT COUNT(*) FROM DELETED) > 0 BEGIN -- UPDATE .... END ELSE IF (SELECT COUNT(*) FROM INSERTED) > 0 BEGIN -- INSERT .... END ELSE BEGIN -- DELETE .... END

>Vi ringrazio anticipatamente
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

walteradrian Profilo | Newbie

Perfetto funziona

Grazie 1000 per il vostro aiuto

Non vorrei abusare della vostra gentilezza ma avrei un'ultima domanda sempre sui trigger.

Ho letto che il formato Text non è supportato dalle tabelle Inserted e deleted, e la fortuna vuole che io sia pieno di campi di formato Text

Avevo pensato di cambiare i Text in varchar(MAX) ma purtroppo non posso modifcare le tabelle.

Esiste un modo per risolvere il problema??

Scusate ancora per il disturbo

Brainkiller Profilo | Guru

>Ho letto che il formato Text non è supportato dalle tabelle Inserted
>e deleted, e la fortuna vuole che io sia pieno di campi di formato
>Text

In curiosito dalla cosa, sono andato anche io a leggere un po' la documentazione. E ho letto però che ci sono problemi su quel tipo di cambi, quando la compatibilità del DB è a 65 o 70. Quando è da 80 in su pare non ci siano problemi, in particolare la frase:

"If the compatibility level is 80 or higher, SQL Server allows the update of text, ntext, or image columns through the INSTEAD OF trigger on tables or views."

Immagino il tuo DB sarà 80 o 90.
Cosa te ne pare ?

Se una delle nostre risposte ti ha soddisfatto, accettala, tramite l'apposito link "Accetta risposta".

Ciao

David De Giacomi | Microsoft MVP
http://blogs.dotnethell.it/david/

walteradrian Profilo | Newbie

Il problema è che io non devo usare INSTEAD OF ma FOR


Nel mio caso il trigger mi serve ad esempio quando modifico un record nella Tabella1 viene scritto nella Tabella2 il record della Tab1 prima della modifica, così da poter tornare allo stato iniziale ripercorrendo al contrario la Tab2 e ripristinando i dati vecchi

Ho provato con INSTEAD OF ma invece di scrivere nella tabella gemella l'operazione effettuata, scrive l'operazione nella tabella gemella senza scriverla nella Tabella principale.

lbenaglia Profilo | Guru

>In curiosito dalla cosa, sono andato anche io a leggere un po'
>la documentazione. E ho letto però che ci sono problemi su quel
>tipo di cambi, quando la compatibilità del DB è a 65 o 70. Quando
>è da 80 in su pare non ci siano problemi, in particolare la frase:
>
>"If the compatibility level is 80 or higher, SQL Server allows
>the update of text, ntext, or image columns through the INSTEAD
>OF trigger on tables or views."
>
>Immagino il tuo DB sarà 80 o 90.
>Cosa te ne pare ?

I BOL riportano anche:

"To retrieve the new value in either an INSERT or UPDATE trigger, join the inserted table with the original update table".

Quindi non vedo particolari problemi, se hai bisogno i nuovi valori delle colonne text, ntext, o image, metti in JOIN la tabella virtuale INSERTED con la tabella base, prelevandoli da quest'ultima (dato che in un after trigger, le modifiche alla tabella base saranno state già eseguite anche se la transazione è ancora in corso).

Ciao!

--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5