ESSAYER … CATCH ne semble pas fonctionner

J'ai le morceau de code suivant juste pour m'assurer que la table temporaire n'existe pas. Si la table existe, je veux la tronquer.

CREATE TABLE #LookupLinks( [SyncID] uniqueidentifier, [Name] nvarchar(50), [SQLTable] nvarchar(50) ) --I create this just to test my try-catch BEGIN TRY CREATE TABLE #LookupLinks( [SyncID] uniqueidentifier, [Name] nvarchar(50), [SQLTable] nvarchar(50) ) END TRY BEGIN CATCH PRINT N'#LookupLinks already existed and was truncated.'; TRUNCATE TABLE #LookupLinks END CATCH 

Ce que je veux faire:

  1. La table temporaire est créée
  2. Essayez de le créer à nouveau
  3. erreur nous envoie dans la capture
  4. la table est tronquée et tout continue comme d'habitude

Ce qui se produit:

ERREUR: Il y a déjà un object nommé '#LookupLinks' dans la database.

Qu'est-ce que je fais mal ici?

C'est parce que SQL Server parsing et valide le lot entier. Ainsi, lors de l'parsing de la deuxième instruction CREATE TABLE , elle se déconnecte en disant:

Il y a déjà un object nommé '#LookupLinks' dans la database.

Voir cet exemple:

 IF 1 = 1 BEGIN CREATE TABLE #temp(col INT) END ELSE BEGIN CREATE TABLE #temp(col INT) END 

Il produit une erreur disant:

Il y a déjà un object nommé '#temp' dans la database.

La solution de contournement consiste à utiliser Dynamic SQL .

 -- CREATE the table for testing IF OBJECT_ID('tempdb..#LookupLinks') IS NOT NULL DROP TABLE #LookupLinks CREATE TABLE #LookupLinks( [SyncID] uniqueidentifier, [Name] nvarchar(50), [SQLTable] nvarchar(50) ) -- Final query IF OBJECT_ID('tempdb..#LookupLinks') IS NOT NULL BEGIN TRUNCATE TABLE #LookupLinks PRINT N'#LookupLinks already existed and was truncated.' END ELSE BEGIN DECLARE @sql NVARCHAR(MAX) = '' SELECT @sql = ' CREATE TABLE #LookupLinks( [SyncID] uniqueidentifier, [Name] nvarchar(50), [SQLTable] nvarchar(50) )' EXEC sp_executesql @sql PRINT N'#LookupLinks was created.' END 

Si vous n'avez pas la première instruction CREATE TABLE , votre requête fonctionnera très bien. Ou si vous mettez un GO avant le BEGIN TRY .

 IF OBJECT_ID('tempdb..#LookupLinks') IS NOT NULL DROP TABLE #LookupLinks -- DROP FIRST CREATE TABLE #LookupLinks( [SyncID] uniqueidentifier, [Name] nvarchar(50), [SQLTable] nvarchar(50) ) --I create this just to test my try-catch GO BEGIN TRY CREATE TABLE #LookupLinks( [SyncID] uniqueidentifier, [Name] nvarchar(50), [SQLTable] nvarchar(50) ) END TRY BEGIN CATCH PRINT N'#LookupLinks already existed and was truncated.'; TRUNCATE TABLE #LookupLinks END CATCH 

Pourtant, c'est parce que SQL Server parsing et valide le lot entier. La déclaration GO mettra les déclarations dans leurs propres lots, ainsi l'erreur ne se produit pas maintenant.

Même la réponse de CeOnSql fonctionnera bien.

TRY CATCH est une erreur d'exécution. Ce que vous obtenez est une erreur de compilation. Ajouter une PRINT 1 avant votre déclaration et vous verrez que rien ne se fait exécuter.

 print 1 CREATE TABLE #LookupLinks( [SyncID] uniqueidentifier, [Name] nvarchar(50), [SQLTable] nvarchar(50) ); BEGIN TRY CREATE TABLE #LookupLinks( [SyncID] uniqueidentifier, [Name] nvarchar(50), [SQLTable] nvarchar(50) ); END TRY BEGIN CATCH PRINT N'#LookupLinks already existed and was truncated.'; TRUNCATE TABLE #LookupLinks END CATCH 

Je pense que ce que vous voulez vraiment accomplir est ceci:

 IF OBJECT_ID('tempdb..#LookupLinks') IS NOT NULL --Table already exists BEGIN TRUNCATE TABLE #LookupLinks PRINT N'#LookupLinks already existed and was truncated.'; END ELSE BEGIN CREATE TABLE #LookupLinks( [SyncID] uniqueidentifier, [Name] nvarchar(50), [SQLTable] nvarchar(50) ) END 

entrez la description de l'image ici