È possibile scegliere RAISERROR o THROW a seconda della versione di SQL Server?


11

Ecco il mio codice adesso:

BEGIN TRY
INSERT INTO TABLE (F1,F2,F3) 
VALUES ('1','2','3')
END TRY
BEGIN CATCH
;THROW
END CATCH

Funziona alla grande, a meno che non sia eseguito su una macchina con SQL 2008. Mi piacerebbe che il blocco CATCH eseguisse un controllo rispetto alla versione SQL ed eseguisse THROW se è uguale o superiore al 2012, e RAISERROR se è il 2008. Continuo a eseguire errori di sintassi e mi chiedo se sia persino possibile. Anche qualcosa di semplice come questo non funziona per me.

BEGIN CATCH
IF ((SELECT SERVERPROPERTY('productversion')) >= 11) ;THROW
END CATCH

Qualsiasi consiglio è apprezzato.

Risposte:


9

No questo non è possibile.

Questa è una sintassi non valida nelle versioni precedenti e causerà un errore di compilazione.

Non è possibile nascondere l' interno di THROWun EXECblocco cattura in quanto un tiro senza parametri deve essere direttamente contenuto all'interno del blocco.

Dovresti distribuire la versione del codice che desideri in base alla versione di SQL Server che stai distribuendo (e sfortunatamente non esiste un buon supporto per questo neanche negli strumenti SSDT di cui sono a conoscenza - nessun equivalente di includere selettivamente le righe di codice attraverso compilazione condizionale)


4

Va sottolineato che, anche se tecnicamente fosse possibile alternare tra THROWe RAISERROR, (molto probabilmente) non si vorrebbe effettivamente farlo. Perché? Perché l'abilità molto nobile del senza parametri THROWdi respingere l'errore usando lo stesso numero di messaggio (cioè Msg 8134invece di Msg Xdove X> = 50000) non è l'unica differenza tra loro: THROWsta interrompendo il batch mentre RAISERRORnon lo è. Questa può essere un'importante differenza comportamentale, come dimostrato di seguito.

Configurazione di prova

--DROP PROC ##Throw;
--DROP PROC ##RaisError;

GO
CREATE PROCEDURE ##Throw
AS
SET NOCOUNT ON;
BEGIN TRY
  SELECT 1/0 AS [DivideByZero];
END TRY
BEGIN CATCH
  THROW;
END CATCH;
SELECT 1 AS [AA];
GO

CREATE PROCEDURE ##RaisError
AS
SET NOCOUNT ON;
BEGIN TRY
  SELECT 1/0 AS [DivideByZero];
END TRY
BEGIN CATCH
  RAISERROR('test, yo!', 16, 1);
  -- RETURN; -- typically at end of CATCH block when using RAISERROR
END CATCH;
SELECT 2 AS [BB];
GO

Test 1

EXEC ##Throw;
SELECT 3 AS [CC];

Ritorna:

"Results" Tab:

DivideByZero
{empty result set}

"Messages" Tab:

Msg 8134, Level 16, State 1, Procedure ##Throw, Line 38
Divide by zero error encountered.

Test 2

EXEC ##RaisError;
SELECT 4 AS [DD];

Ritorna:

"Results" Tab:

DivideByZero
{empty result set}

BB
2

DD
4

"Messages" Tab:

Msg 50000, Level 16, State 1, Procedure ##RaisError, Line 45
test, yo!

Ad essere onesti, è possibile mascherare questa differenza procedendo come segue:

  • Avvolgi sempre tutte le chiamate al codice usando THROWall'interno di un TRY...CATCHcostrutto (illustrato di seguito)
  • Non inserire mai il codice dopo il THROW(bene, tranne per END CATCH;)

Test 3

BEGIN TRY
  EXEC ##Throw;
  SELECT 5 AS [EE];
END TRY
BEGIN CATCH
  SELECT ERROR_NUMBER() AS [ErrorNumber], ERROR_MESSAGE() AS [ErrorMessage];
END CATCH;
SELECT 6 AS [FF];
GO

Ritorna:

"Results" Tab:

DivideByZero
{empty result set}

ErrorNumber     ErrorMessage
8134            Divide by zero error encountered.

FF
6

Test 4

BEGIN TRY
  EXEC ##RaisError;
  SELECT 7 AS [GG];
END TRY
BEGIN CATCH
  SELECT ERROR_NUMBER() AS [ErrorNumber], ERROR_MESSAGE() AS [ErrorMessage];
END CATCH;
SELECT 8 AS [HH];
GO

Ritorna:

"Results" Tab:

DivideByZero
{empty result set}

ErrorNumber     ErrorMessage
50000           test, yo!

HH
8

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.