none
Come impedisco l'inserimento di un dato in tabella al verificarsi di un trigger? RRS feed

  • Domanda

  • buonasera,

    ho una tabella sulla quale esiste un trigger. L'azione di questo trigger è solo quello di fare una SELECT ( senza IF ne altro ) per ricercare determinati record rispettando le condizioni definite nel WHERE. Lo scopo è quello di verificare, prima dell'inserimento di un certo dato, se tale dato esiste anche in un'altra tabella ( sottolineo che non posso usare chiavi esterne od altro, sono costretto per motivi di studio ad usare un trigger ), nel caso in cui non esista allora l'inserimento non può essere fatto. Il trigger funzionava bene fino a quando non ho deciso di mettere un blocco exception che registra le eccezioni in una tabella ERRORE. Quello che succede è che quando il trigger si avvia trova l'eccezione ( entra quindi nel blocco exception ) e la tabella ERRORE viene aggiornata, tuttavia il dato che sto inserendo viene inserito mentre quando io voglio che tutto il record non venga inserito. Cosa posso fare? Sono costretto ad usare degli IF e non solo la SELECT? Grazie.

    mercoledì 6 novembre 2013 16:40

Risposte

  • salve,

    ovviamente sto a sottolineare che vedere il tuo codice, opportunamente semplificato per essere autonomo qui, aiuterebbe molto... :)

    al di la' di cio', di seguito un esempio triviale, 

    SET NOCOUNT ON;
    USE tempdb;
    GO
    CREATE TABLE dbo.Errori (
    	Spid int NOT NULL,
    	ErrTime datetime NOT NULL,	
    	UserName sysname NOT NULL,
    	Data varchar(100)
    	);
    CREATE TABLE dbo.TestTB (
    	Id int NOT NULL,
    	rowTime date NOT NULL
    	);
    CREATE TABLE dbo.ReferTB (
    	Id int NOT NULL,
    	rowTime date NOT NULL
    	);
    GO
    CREATE TRIGGER TestTB_I__
        ON [dbo].[TestTB]
        FOR INSERT
    AS BEGIN
    	IF @@ROWCOUNT = 0 RETURN;
    
        SET NOCOUNT ON;
    	IF EXISTS (
    		SELECT *
    			FROM inserted i
    				JOIN dbo.ReferTB r ON r.rowTime = i.rowTime
    			) BEGIN
    
    		ROLLBACK;
    		INSERT INTO dbo.Errori
    			SELECT @@SPID, CURRENT_TIMESTAMP, CURRENT_USER, 'Le righe da inserire sono presenti in altra tabella';			
    			RAISERROR ('Le righe da inserire sono presenti in altra tabella', 16, 1);
    			RETURN
    		END;
    END;
    GO
    INSERT INTO dbo.ReferTB
    	VALUES ( 1, '20131031' );
    GO
    INSERT INTO dbo.TestTB
    	VALUES ( 1, '20130101' );
    SELECT *
    	FROM dbo.TestTB;
    GO
    INSERT INTO dbo.TestTB
    	VALUES ( 2, '20131031' );
    GO
    SELECT *
    	FROM dbo.TestTB;
    SELECT *
    	FROM dbo.Errori;
    GO
    DROP TABLE dbo.Errori, dbo.TestTB, dbo.ReferTB;
    --<----------
    Id          rowTime
    ----------- ----------
    1           2013-01-01
    
    Msg 50000, Level 16, State 1, Procedure TestTB_I__, Line 17
    Le righe da inserire sono presenti in altra tabella
    Msg 3609, Level 16, State 1, Line 1
    The transaction ended in the trigger. The batch has been aborted.
    Id          rowTime
    ----------- ----------
    1           2013-01-01
    
    Spid        ErrTime                 UserName  Data
    ----------- ----------------------- --------- ----------------------------------------------------
    53          2013-11-08 11:03:45.570 dbo       Le righe da inserire sono presenti in altra tabella
    

    quindi un blocco condizionale direi che ovviamente ci vuole, e nel caso il riscontro sia positivo devi impostare il rollback del trigger sui dati inseriti e registrare l'errore nella tua tabella di appoggio errori...

    saluti


    http://www.hotelsole.com/asql/index.php - DbaMgr2k - DbaMgr and further SQL Tools http://www.hotelsole.com/

    venerdì 8 novembre 2013 10:18
    Moderatore