web-dev-qa-db-fra.com

Comment obtenir le nombre de lignes de EXEC () dans un SPROC TSQL?

J'ai un sproc TSQL qui construit une requête et l'exécute comme suit:

EXEC (@sqlTop + @sqlBody + @sqlBottom)

@sqlTop contient quelque chose comme SELECT TOP (x) col1, col2, col3 ... 

TOP (x) limitera le nombre de lignes renvoyées. Je souhaite par la suite connaître le nombre réel de lignes de la table correspondant à la requête.

J'ai ensuite remplacé @sqlTop par quelque chose comme:

EXEC ('SELECT @ActualNumberOfResults = COUNT(*) ' + @sqlBody)

Je peux voir pourquoi cela ne fonctionne pas et pourquoi une erreur non déclarée de valeur se produit, mais je pense que cela décrit correctement ce que j'essaie d'accomplir.

Des idées?

18
ElHaix

Au lieu de cela, la requête dynamique pourrait renvoyer le résultat sous la forme d'un ensemble de lignes, que vous inséreriez ensuite dans une variable de table (pouvant également être une table temporaire ou ordinaire) à l'aide de la syntaxe INSERT ... EXEC. Ensuite, vous pouvez simplement lire la valeur enregistrée dans une variable à l'aide de SELECT @var = ...:

DECLARE @rowcount TABLE (Value int);
INSERT INTO @rowcount
EXEC('SELECT COUNT(*) ' + @sqlBody);
SELECT @ActualNumberOfResults = Value FROM @rowcount;
15
Andriy M

En fin de journée, mais j'ai trouvé cette méthode beaucoup plus simple:

-- test setup
DECLARE @sqlBody nvarchar(max) = N'SELECT MyField FROM dbo.MyTable WHERE MyOtherField = ''x''';
DECLARE @ActualNumberOfResults int;

-- the goods
EXEC sp_executesql @sqlBody;
SET @ActualNumberOfResults = @@ROWCOUNT;
SELECT @ActualNumberOfResults;
13
downwitch

utilisez sp_executesql et un output parameter

exemple

DECLARE @sqlBody VARCHAR(500),@TableCount INT, @SQL NVARCHAR(1000)

SELECT @sqlBody = 'from sysobjects'
SELECT @SQL = N'SELECT @TableCount = COUNT(*) ' + @sqlBody

EXEC sp_executesql @SQL, N'@TableCount INT OUTPUT', @TableCount OUTPUT

SELECT @TableCount
GO
10
SQLMenace

Après avoir exécuté votre requête, stockez le résultat de @@ROWCOUNT dans toute variable que vous pourrez utiliser plus tard.

EXEC sp_executesql 'SELECT TOP 10 FROM ABX' 

SET @TotRecord = @@ROWCOUNT dans votre variable pour une utilisation ultérieure.

2
user4815065

N'oubliez pas que le SQL dynamique a sa propre portée. Toute variable déclarée/modifiée à cet endroit sera hors de portée après votre EXEC ou votre sp_executesql.

Suggérez l'écriture dans une table temporaire, qui sera dans la portée de votre instruction SQL dynamique et à l'extérieur.

Peut-être le mettre dans votre sqlBottom:

CREATE TABLE ##tempCounter(MyNum int);

EXEC('SELECT @ActualNumberOfResults = COUNT(*) ' + @sqlBody + 
       '; INSERT INTO ##tempCounter(MyNum) VALUES(@ActualNumberOfResults);');

SELECT MyNum FROM ##tempCounter;
1
p.campbell

Le seul problème avec les réponses qui créent des tables temporaires (en utilisant "DECLARE @rowcount TABLE" ou "CREATE TABLE ## tempCounter (MyNum int)") est que vous devez lire tous les enregistrements affectés hors du disque en mémoire. Si vous attendez un grand nombre d'enregistrements, cela peut prendre un certain temps.

Donc, si la réponse est susceptible d’être volumineuse, la solution "utiliser sp_executesql et un paramètre de sortie" est une réponse plus efficace. Et cela semble fonctionner.

0
andyabel