Gestione degli errori: manca ancora qualcosa
Con SQL Server 2005 (e l'introduzione delle keyword TRY / CATCH) la gestione degli errori è notevolmente migliorata.
Dalla precedente versione possiamo ad esempio sfruttare, all'interno di un blocco BEGIN CATCH ... END CATCH le funzioni scalari ERROR_NUMBER(), ERROR_MESSAGE(), ... per tracciare tutte le informazioni relative all'eccezione generata, così che possa loggarle, memorizzarle in una mia tabella, ecc...
Il problema però è che, essendo scalari, queste funzioni ritornano soltanto un valore e non una possibile lista di errori generati.
Mi spiego con un esempio...
Creo una tabella molto semplice, con una sola colonna, su cui applico un vincolo UNIQUE.
In questo modo:
USE tempdb
GO
IF OBJECT_ID('dbo.tabTest', 'U') IS NOT NULL
DROP TABLE dbo.tabTest
GO
CREATE TABLE tabTest (codice INT)
GO
ALTER TABLE tabTest WITH CHECK
ADD CONSTRAINT u_tabTest UNIQUE (codice)
go
A questo punto, chissà per quale motivo, viene rieseguita, all'interno di un blocco TRY / CATCH, l'istruzione di creazione del medesimo constraint:
BEGIN TRY
ALTER TABLE tabTest WITH CHECK
ADD CONSTRAINT u_tabTest UNIQUE (codice)
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
END CATCH
Cosa ottengo?
Una sola riga con l'ultimo errore generato: non posso creare il vincolo. Vedi gli errori precedenti.
Ok, ma come diavolo faccio a vedere gli errori precedenti ?!?!
Infatti, nella realtà, gli errori sarebbero due ed il primo molto più chiaro del secondo:
Msg 2714, Level 16, State 4, Line 1
There is already an object named 'u_tabTest' in the database.
Msg 1750, Level 16, State 0, Line 1
Could not create constraint. See previous errors.
Purtroppo non esiste il modo di recuperare entrambi gli errori, nè esiste il modo di intercettare i messaggi che vengono visualizzati sulla finestra "Messages" del Management Studio.
Con SQL 2008 cambia qualcosa?
Putroppo no, o meglio, cambia solo il numero di errore e la descrizione del primo messaggio:
Msg 1913, Level 16, State 1, Line 2
The operation failed because an index or statistics with name 'u_tabTest' already exists on table 'tabTest'.
Msg 1750, Level 16, State 0, Line 2
Could not create constraint. See previous errors.