Les subtilités d'exec dans TSQL

Cette procédure stockée

CREATE PROC GetPage(@blockNumber int, @blockSize int = 40, @query varchar(1000)) AS DECLARE @a int = @blockNumber * @blockSize; DECLARE @b int = @a + @blockSize - 1; DECLARE @fromPos int = PATINDEX('% FROM %', @query); DECLARE @from varchar(1000) = SUBSTRING(@query, @fromPos, 1000); DECLARE @select varchar(1000) = SUBSTRING(@query, 1, @fromPos); DECLARE @SQL varchar(1000) = 'select *, ROW_NUMBER() over (order by ONE) R INTO #FOO FROM (' +@SELECT+',1 ONE'+@from+') T'; EXEC @SQL; SELECT * FROM FOO WHERE RN BETWEEN @a AND @b; DECLARE @C INT = (SELECT COUNT(*) FROM #FOO); DROP TABLE #FOO RETURN @C; 

lorsqu'il est passé SELECT * FROM ASSET génère ce SQL

 select *, ROW_NUMBER() over (order by ONE) R INTO #FOO FROM (select * ,1 ONE from asset) T 

Lorsque j'exécute cela à partir de SQL Server Management Studio, comme ceci:

 exec('select *, ROW_NUMBER() over (order by ONE) R INTO #FOO FROM (select * ,1 ONE from asset) T') 

il crée la table #FOO comme prévu.

Cependant, lorsque la procédure stockée est exécutée:

 exec getpage 5,10,'select * from asset' 

J'ai cette erreur

Msg 2812, niveau 16, état 62, procédure GetPage, ligne 12
Impossible de find la procédure stockée 'select *, ROW_NUMBER () sur (command par ONE) R INTO FOO FROM (select *, 1 ONE de l'actif) T'.
Msg 208, niveau 16, état 1, procédure GetPage, ligne 14
Nom d'object non valide "#FOO".

Je pense que le deuxième message est simplement une conséquence de la première erreur. Est-ce que quelqu'un sait pourquoi l'instruction exec se comporte différemment dans une procédure stockée?

Utilisez des parenthèses dans votre exec

 EXEC (@SQL); 

EXECUTE (Transact-SQL)

Sans la parenthèse, vous utilisez ceci:

 Exécuter une procédure stockée ou une fonction
 [{EXEC |  EXECUTE}]
     { 
       [@return_status =]
       {nom_module [; numéro] |  @module_name_var } 
         [[@parameter =] {valeur 
                            |  @variable [OUTPUT] 
                            |  [ DÉFAUT ] 
                            }
         ]
       [, ... n]
       [AVEC [, ... n]]
     }
 [;]

Vous voulez ceci où la parenthèse est exigée.

 Exécuter une string de caractères
 {EXEC |  EXÉCUTER} 
     ({ @ssortingng_variable | [N] 'tsql_ssortingng'} [+ ... n])
     [AS {CONNEXION |  USER} = 'nom']
 [;]