Non, le script ci-dessus ne fonctionne pas et se déroule exactement comme vous vous y attendez :
Begin Try
Declare @SQL NVarchar(Max)='Exec [MyLinkedServer].master.dbo.sp_executesql N''Drop Table [tempdb].dbo.[T1]''';
Print @SQL;
Exec master.dbo.sp_executesql @SQL;
End Try
Begin Catch
print 'dans le catch'
Print Error_Message()
End Catch
Exec [MyLinkedServer].master.dbo.sp_executesql N'Drop Table [tempdb].dbo.[T1]'
dans le catch
Impossible de trouver le serveur 'MyLinkedServer' dans sys.servers. Vérifiez que le nom du serveur correct a été spécifié. Si nécessaire, exécutez la procédure stockée sp_addlinkedserver pour ajouter le serveur à sys.servers.
Voyez ce message 'dans le catch' ? C'est la preuve que le bloc catch a été exécuté.
Mais vous avez raison, il y a en effet un problème bien connu selon lequel les erreurs de compilation ne peuvent pas être capturées dans l'étendue où elles se produisent. Ce qui est tout à fait attendu, c'est comme demander à un bloc catch dans un programme C# de s'exécuter lorsque le code ne compile pas... Le problème est bien expliqué en détail à l'adresse Gestion des erreurs en SQL 2005 et ultérieurs. Vous devez créer une portée externe pour capturer l'erreur de compilation qui se produit dans la portée interne. Ce qui est exactement ce que vous faites dans votre exemple posté !