2008-09-12 7 views
36

J'utilise SQL Server 2005 et j'aimerais savoir comment accéder à différents ensembles de résultats à partir de transact-sql. La procédure stockée suivante renvoie deux ensembles de résultats, comment puis-je y accéder, par exemple, une autre procédure stockée?Accès aux ensembles de résultats depuis Procédures stockées Transact-SQL SQL Server

CREATE PROCEDURE getOrder (@orderId as numeric) AS 
BEGIN 
    select order_address, order_number from order_table where order_id = @orderId 
    select item, number_of_items, cost from order_line where order_id = @orderId 
END 

Je dois être en mesure de parcourir individuellement les deux ensembles de résultats.

EDIT: Juste pour clarifier la question, je veux tester les procédures stockées. J'ai un ensemble de procédures stockées qui sont utilisées à partir d'un client VB.NET, qui renvoient plusieurs jeux de résultats. Ceux-ci ne vont pas être remplacés par une fonction de valeur de table, je ne peux pas changer les procédures du tout. Changer la procédure n'est pas une option.

Les ensembles de résultats renvoyés par les procédures ne sont pas les mêmes types de données ou le même nombre de colonnes.

Répondre

34

La réponse courte est: vous ne pouvez pas le faire. À partir de T-SQL, il n'existe aucun moyen d'accéder à plusieurs résultats d'un appel de procédure stockée imbriqué, sans modifier la procédure stockée comme d'autres l'ont suggéré.

Pour être complet, si la procédure revenions un seul résultat, vous pouvez l'insérer dans une table temporaire ou variable de table avec la syntaxe suivante:

INSERT INTO #Table (...columns...) 
EXEC MySproc ...parameters... 

Vous pouvez utiliser la même syntaxe pour une procédure renvoie plusieurs résultats, mais il ne traitera que le premier résultat, le reste sera ignoré.

+2

Je viens de tester la solution de Brannon, et en fait, si toutes les requêtes de la procédure stockée appelée retournent le même nombre de colonnes et de types de données, l'ensemble de résultats sera une union des ensembles de résultats. Ce qui est à peu près inutile. Merci pour votre aide. –

0

Vous pouvez les sélectionner dans des tables temporaires ou écrire des fonctions de table pour renvoyer des ensembles de résultats. Vous demandez comment parcourir les ensembles de résultats?

1

Il y a deux façons de le faire facilement. Coller les résultats dans une table temporaire, puis référencer la table temporaire depuis votre sproc. L'autre alternative consiste à placer les résultats dans une variable XML utilisée comme variable OUTPUT.

Il y a, cependant, des avantages et des inconvénients à ces deux options. Avec une table temporaire, vous devrez ajouter du code au script qui crée la procédure d'appel pour créer la table temporaire avant de modifier la procédure. En outre, vous devez nettoyer la table temporaire à la fin de la procédure.

Avec le XML, il peut être intensif en mémoire et lent.

4

Notez qu'il existe une limitation supplémentaire non documentée dans l'instruction INSERT INTO ... EXEC: elle ne peut pas être imbriquée. C'est-à-dire que le processus stocké que les appels EXEC (ou tout ce qu'il appelle à son tour) ne peut pas faire lui-même un INSERT INTO ... EXEC. Il semble qu'il y ait un seul bloc-notes par processus qui accumule le résultat, et s'ils sont imbriqués, vous obtiendrez une erreur lorsque l'appelant l'ouvrira, puis l'appelé tentera de l'ouvrir à nouveau. Matthieu, vous auriez besoin de maintenir des tables temporaires distinctes pour chaque "type" de résultat. En outre, si vous exécutez le même plusieurs fois, vous devrez peut-être ajouter une colonne supplémentaire à ce résultat pour indiquer de quel appel il est issu.

2

Malheureusement, il est impossible de le faire. Le problème est, bien sûr, qu'il n'y a pas de syntaxe SQL pour l'autoriser. Cela se passe bien sûr sous le capot, mais vous ne pouvez pas obtenir ces autres résultats dans TSQL, seulement à partir de l'application via ODBC ou autre.

Il y a un moyen de contourner cela, comme avec la plupart des choses. L'astuce consiste à utiliser ole automation dans TSQL pour créer un objet ADODB qui ouvre chaque jeu de résultats à tour de rôle et écrit les résultats dans les tables que vous nommez (ou faites ce que vous voulez avec les résultats). vous pouvez également le faire dans DMO si vous aimez la douleur.

8

J'ai facilement pu le faire en créant une procédure stockée SQL2005 CLR qui contenait un jeu de données interne.

Vous voyez, un nouvel objet SqlDataAdapter remplira un sproc à plusieurs jeux de résultats dans un ensemble de données à tables multiples par défaut. Les données de ces tables peuvent à leur tour être insérées dans les tables #Temp du sproc appelant que vous souhaitez écrire. dataset.ReadXmlSchema va vous montrer le schéma de chaque ensemble de résultats.

Etape 1: Commencez à écrire le sproc qui lit les données de la sproc multi-jeu de résultats

a. Créez une table distincte pour chaque jeu de résultats en fonction du schéma.

CREATE PROCEDURE [dbo].[usp_SF_Read] AS 
SET NOCOUNT ON; 
CREATE TABLE #Table01 (Document_ID VARCHAR(100) 
    , Document_status_definition_uid INT 
    , Document_status_Code VARCHAR(100) 
    , Attachment_count INT 
    , PRIMARY KEY (Document_ID)); 

b. À ce stade, vous devrez peut-être déclarer un curseur pour appeler répétitivement le CLR sproc vous créerez ici:

Étape 2: le Sproc CLR

Partial Public Class StoredProcedures 
    <Microsoft.SqlServer.Server.SqlProcedure()> _ 
    Public Shared Sub usp_SF_ReadSFIntoTables() 

    End Sub 
End Class 

a. Se connecter en utilisant New SqlConnection("context connection=true").

b. Configurez un objet de commande (cmd) pour contenir le sproc à jeux de résultats multiples.

c. Obtenez toutes les données en utilisant ce qui suit:

Dim dataset As DataSet = New DataSet 
    With New SqlDataAdapter(cmd) 
     .Fill(dataset) ' get all the data. 
    End With 
'you can use dataset.ReadXmlSchema at this point... 

d. Itérez sur chaque table et insérez chaque ligne dans la table temporaire appropriée (que vous avez créée dans la première étape ci-dessus). Dans mon expérience, vous voudrez peut-être imposer certaines relations entre vos tables afin de savoir de quel groupe provient chaque enregistrement.

C'est tout ce qu'il y avait à faire!

~ Shaun, près de Seattle

+0

Alors que SQLCLR est le seul moyen de résoudre réellement ce problème, le fait de passer facilement à un 'DataSet' n'est pas évolutif, car tous les résultats de tous les jeux de résultats seront en mémoire. La méthode la plus appropriée/évolutive consiste à parcourir une 'SqlDataReader' et à retourner chaque ligne telle qu'elle est lue dans' SqlDataReader'. La réponse de DanRadu ici, en dehors de ne pas manipuler tous les types de données (un raccourci réparable), envoie chaque ligne comme elle est lue: http://stackoverflow.com/questions/6388489/insert-into-temp-table-from-a -stored-procedure-that-returns-multiple-résultats-sets/11045189 # 11045189 –

5

Il y a une bidouille que vous pouvez faire aussi bien. Ajoutez un paramètre facultatif N int à votre sproc. Par défaut la valeur de N à -1. Si la valeur de N est -1, effectuez chacune de vos sélections. Sinon, faites la Nième sélection et seulement la Nième sélection.

Par exemple,

if (N = -1 or N = 0) 
    select ... 

if (N = -1 or N = 1) 
    select ... 

Les appelants de votre sproc qui ne spécifient pas N recevront un jeu de résultats avec plus d'une table. Si vous avez besoin d'extraire une ou plusieurs de ces tables d'un autre sproc, appelez simplement votre sproc en spécifiant une valeur pour N. Vous devrez appeler le sproc une fois pour chaque table que vous souhaitez extraire. Inefficace si vous avez besoin de plus d'une table dans le jeu de résultats, mais cela fonctionne en TSQL pur.

Questions connexes