SQL Server sürümüne bağlı olarak RAISERROR veya THROW seçmek mümkün mü?


11

İşte benim kod şu anda:

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

SQL 2008 ile bir makinede çalıştırılmadığı sürece harika çalışıyor. CATCH bloğunun SQL sürümüne karşı bir kontrol yapmasını ve 2012'ye eşit veya daha yüksekse THROW'u ve 2008 ise RAISERROR'u çalıştırmasını istiyorum. sözdizimi hataları ve hatta mümkün olup olmadığını merak ediyorum. Böyle basit bir şey bile benim için çalışmıyor.

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

Herhangi bir tavsiye için teşekkür ederiz.

Yanıtlar:


9

Hayır, bu mümkün değil.

Bu, önceki sürümlerde geçersiz sözdizimidir ve derleme hatasına neden olur.

Gizlemek mümkün değildir THROWbir in EXECparametresiz atmak doğrudan catch içinde bulunan edilmelidir olarak ya catch bloğunun içinde.

İstediğiniz kod sürümünü, dağıtmakta olduğunuz SQL Server sürümüne göre dağıtmanız gerekir (ve ne yazık ki bunun farkında olduğum SSDT takımında bunun için iyi bir destek yoktur - kod satırlarını seçici olarak eklemenin eşdeğeri yoktur) koşullu derleme)


4

Şunu belirtmek gerekir ki, ve teknik olarak teknik olarak mümkün olsa bile THROWve RAISERRORmuhtemelen (muhtemelen) bunu gerçekten yapmak istemezsiniz. Neden? Parametresiz çok şık yeteneği Çünkü THROWkullanarak hatayı yeniden atmak aynı İleti Sayısı (yani Msg 8134yerine Msg Xnerede X> = 50000) aralarındaki tek fark değil: THROWbir toplu iptal süre RAISERRORdeğildir. Bu, aşağıda gösterildiği gibi önemli bir davranış farkı olabilir.

Test kurulumu

--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];

İadeler:

"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];

İadeler:

"Results" Tab:

DivideByZero
{empty result set}

BB
2

DD
4

"Messages" Tab:

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

Adil olmak gerekirse, bu farkı aşağıdakileri yaparak maskelemek mümkündür:

  • Kodun tüm çağrılarını her zamanTHROW bir TRY...CATCHyapı içinde kullanın (aşağıda gösterilmiştir)
  • Hiçbir zaman yer kodundan sonraki THROW(iyi, için hariç 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

İadeler:

"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

İadeler:

"Results" Tab:

DivideByZero
{empty result set}

ErrorNumber     ErrorMessage
50000           test, yo!

HH
8

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.