web-dev-qa-db-fra.com

Comment retourner une table temporaire à partir d'une procédure stockée

CREATE PROCEDURE [test].[proc]
@ConfiguredContentId int,
@NumberOfGames int
AS
BEGIN
 SET NOCOUNT ON
 RETURN 
 @WunNumbers TABLE (WinNumb int)

    INSERT INTO @WunNumbers (WinNumb)
 SELECT TOP (@NumberOfGames) WinningNumber
 FROM [Game].[Game] g
 JOIN [Game].[RouletteResult] AS rr ON g.[Id] = rr.[gameId]
 WHERE g.[ConfiguredContentId] = @ConfiguredContentId
 ORDER BY g.[Stoptime] DESC

 SELECT WinNumb, COUNT (WinNumb) AS "Count"
 FROM @WunNumbers wn
 GROUP BY wn.[WinNumb]
END
GO

Cette procédure stockée renvoie les valeurs de la première instruction select, mais j'aimerais que les valeurs de la deuxième instruction select soient renvoyées. Table @WunNumbers est une table temporaire.

Des idées???

15
dani

Quelle version de SQL Server utilisez-vous? Dans SQL Server 2008, vous pouvez utiliser Paramètres de table et types de table .

Une approche alternative consiste à renvoyer une variable de table à partir d'une fonction définie par l'utilisateur, mais je ne suis pas un grand fan de cette méthode.

Vous pouvez trouver un exemple ici

6
John Sansom

Regardez ce code,

CREATE PROCEDURE Test

AS
    DECLARE @tab table (no int, name varchar(30))

    insert @tab  select eno,ename from emp  

    select * from @tab
RETURN
27
adatapost

Une table temporaire peut être créée dans l'appelant, puis renseignée à partir du SP appelé. 

  create table #GetValuesOutputTable(
     ...   
  );

  exec GetValues; -- populates #GetValuesOutputTable

  select * from #GetValuesOutputTable;

Certains avantages de cette approche par rapport à "insert exec" est qu’elle peut être imbriquée et qu’elle peut être utilisée en entrée ou en sortie. 

Certains inconvénients sont que "l'argument" n'est pas public, la création de la table existe dans chaque appelant et que le nom de la table peut entrer en collision avec d'autres objets temporaires. Il est utile que le nom de la table temporaire corresponde étroitement au nom SP et respecte certaines conventions.

En prenant un peu plus loin, pour les tables en sortie uniquement en sortie, les méthodes insert-exec et table temp peuvent être prises en charge simultanément par le SP appelé. Cela n'aide pas beaucoup pour l'enchaînement des SP, car la table doit encore être définie dans l'appelant, mais peut aider à simplifier les tests à partir de la ligne cmd ou lors d'un appel externe.

  -- The "called" SP
  declare
      @returnAsSelect bit = 0;

  if object_id('tempdb..#GetValuesOutputTable') is null
  begin
      set @returnAsSelect = 1;
      create table #GetValuesOutputTable(
         ...   
      );
  end

  -- populate the table

  if @returnAsSelect = 1
      select * from #GetValuesOutputTable;
3
crokusek

Le type de retour d'une procédure est int.

Vous pouvez également renvoyer des ensembles de résultats (comme votre code le fait actuellement) (d'accord, vous pouvez également envoyer des messages, qui sont des chaînes).

Ce sont les seuls "retours" que vous pouvez faire. Bien que vous puissiez ajouter des paramètres table à une procédure (voir BOL), ils sont uniquement entrés.

Modifier:

(Ou comme un autre poster mentionné, vous pouvez également utiliser une fonction à valeur de table, plutôt qu'une procédure)

0

Commencez par créer une table permanente réelle en tant que modèle contenant la présentation requise pour la table temporaire renvoyée, en utilisant une convention de dénomination qui l'identifie en tant que modèle et la lie de manière symbolique au SP, par exemple tmp_SPName_Output . Cette table ne contiendra jamais aucune donnée.

Dans le SP, utilisez INSERT pour charger des données dans une table temporaire suivant la même convention de dénomination, par exemple. #SPName_Output qui est supposé exister. Vous pouvez tester son existence et renvoyer une erreur si ce n'est pas le cas.

Avant d'appeler le sp, utilisez cette sélection simple pour créer la table temporaire:

SELECT TOP(0) * INTO #SPName_Output FROM tmp_SPName_Output;
EXEC SPName;
-- Now process records in #SPName_Output;

Cela a ces avantages distincts:

  • La table temporaire étant locale à la session en cours, à la différence de ##, elle ne se heurtera pas aux appels simultanés au SP à partir de différentes sessions Il est également supprimé automatiquement lorsqu'il est hors de portée.
  • La table de modèle est maintenue à côté du SP, donc si des modifications sont apportées à la sortie (nouvelles colonnes ajoutées, par exemple), les appelants .__ préexistants du SP ne sont pas interrompus. L'appelant n'a pas besoin d'être changé.
  • Vous pouvez définir un nombre quelconque de tables en sortie avec des noms différents pour One SP et les remplir toutes. Vous pouvez également définir des sorties alternatives Avec des noms différents et demander au SP de vérifier l'existence des tables temp Pour déterminer celles qui doivent être remplies.
  • De même, si des modifications majeures sont apportées mais que vous souhaitez conserver la compatibilité En amont, vous pouvez créer une nouvelle table de modèle et attribuer un nom à la version Ultérieure, tout en prenant en charge la version précédente en vérifiant la table temp De l'appelant. a créé.
0
JohnRC

OUI, VOUS POUVEZ.

Dans votre procédure stockée, vous remplissez la table @tbRetour.

A la toute fin de votre procédure stockée, vous écrivez: 

SELECT * FROM @tbRetour 

Pour exécuter la procédure stockée, vous écrivez:

USE [...]
GO

DECLARE @return_value int

EXEC @return_value = [dbo].[getEnregistrementWithDetails]
@id_enregistrement_entete = '(guid)'

GO
0
André Millaire