2008-09-12 15 views
36

sto usando SQL Server 2005, e vorrei sapere come accedere differenti set di risultati dall'interno di Transact-SQL. La seguente stored procedure restituisce due set di risultati, come posso accedervi, ad esempio, da un'altra stored procedure?accesso al set di risultati dall'interno stored procedure 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 

Devo essere in grado di scorrere individualmente entrambi i set di risultati.

EDIT: Giusto per chiarire la questione, voglio testare le stored procedure. Ho una serie di stored procedure che vengono utilizzate da un client VB.NET, che restituisce più set di risultati. Queste non saranno modificate in una funzione valutata a livello di tabella, non posso in effetti cambiare le procedure. Cambiare la procedura non è un'opzione.

I set di risultati restituiti dalle procedure non sono gli stessi tipi di dati o numero di colonne.

risposta

34

La risposta breve è: non si può fare.

Da T-SQL non c'è modo per accedere a più risultati di una chiamata di stored procedure nidificate, senza modificare la stored procedure come altri hanno suggerito.

per essere completa, se la procedura stavano tornando un singolo risultato, si potrebbe inserirla in una tabella temporanea o variabile di tabella con la seguente sintassi:

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

È possibile utilizzare la stessa sintassi per una procedura che restituisce più risultati, ma elaborerà solo il primo risultato, il resto verrà scartato.

+2

Ho appena testato la soluzione di Brannon e, in effetti, se tutte le query all'interno della stored procedure richiamata restituiscono lo stesso numero di colonne e tipi di dati, il set di risultati restituito consisterà in un'unione dei set di risultati. Che è praticamente inutile. Grazie per il vostro aiuto. –

0

Li possibile selezionare in tabelle temporanee o scrivere funzioni con valori di tabella di restituire set di risultati. Stai chiedendo come iterare attraverso i set di risultati?

1

Ci sono due modi per farlo facilmente. O incollare i risultati in una tabella temporanea e quindi fare riferimento alla tabella temporanea dal proprio sproc. L'altra alternativa consiste nel mettere i risultati in una variabile XML che viene utilizzata come variabile OUTPUT.

Vi sono, tuttavia, pro e contro per entrambe le opzioni. Con una tabella temporanea, è necessario aggiungere codice allo script che crea la procedura chiamante per creare la tabella temporanea prima di modificare la procedura. Inoltre, è necessario pulire la tabella temporanea alla fine della procedura.

Con l'XML, può essere intensivo di memoria e lento.

4

Nota che c'è un extra, la limitazione non documentata alla INSERT INTO ... EXEC: non può essere nidificato. Cioè, il processo memorizzato che le chiamate EXEC (o qualsiasi altra chiamata a sua volta) non può fare da solo INSERT INTO ... EXEC. Sembra che ci sia un singolo scratchpad per processo che accumula il risultato, e se sono nidificati si otterrà un errore quando il chiamante lo apre, e poi il callee prova ad aprirlo di nuovo.

Matthieu, avresti bisogno di mantenere tabelle temporanee separati per ogni "tipo" di risultato. Inoltre, se stai eseguendo lo stesso più volte, potresti dover aggiungere una colonna aggiuntiva a quel risultato per indicare da quale chiamata proviene.

2

Purtroppo è impossibile farlo. Il problema è, naturalmente, che non esiste una sintassi SQL per consentirlo. Succede "sotto il cofano", ovviamente, ma non è possibile ottenere questi altri risultati in TSQL, solo dall'applicazione tramite ODBC o altro.

C'è un modo per aggirarlo, come con la maggior parte delle cose. Il trucco consiste nell'utilizzare l'automazione ole in TSQL per creare un oggetto ADODB che apre a turno ogni set di risultati e scrive i risultati nelle tabelle da te nominate (o fai quello che vuoi con i gruppi di risultati). puoi anche farlo in DMO se ti piace il dolore.

8

Sono stato in grado di farlo facilmente creando una stored procedure CLR SQL2005 che conteneva un set di dati interno.

Vedete, un nuovo SqlDataAdapter completerà uno sproc set di risultati multipli in un dataset a più tabelle per impostazione predefinita. I dati in queste tabelle possono a loro volta essere inseriti nelle tabelle #Temp nel campo di chiamata che si desidera scrivere. dataset.ReadXmlSchema ti mostrerà lo schema di ogni set di risultati.

Fase 1: iniziare a scrivere lo sProc che leggere i dati dal multi-risultato-set sproc

a. Creare una tabella separata per ogni set di risultati in base allo schema.

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. A questo punto potrebbe essere necessario dichiarare un cursore a chiamare ripetutamente il CLR sproc si creerà qui:

Fase 2: Fare il CLR Sproc

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

    End Sub 
End Class 

a. Connetti usando New SqlConnection("context connection=true").

b. Impostare un oggetto comando (cmd) per contenere lo sproc di risultati multipli.

c. Ottenere tutti i dati utilizzando il seguente:

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. Scorrere su ogni tabella e inserire ogni riga nella tabella temporanea appropriata (creata nel passaggio uno sopra).

Nota finale: Nella mia esperienza, si potrebbe desiderare di far rispettare alcune relazioni tra le tabelle in modo da sapere che in batch ogni record è venuto da.

Questo è tutto quello che c'è da fare!

~ Shaun, vicino a Seattle

+0

Mentre SQLCLR è l'unico modo per risolvere effettivamente questo problema, il facile percorso di dumping verso un 'DataSet' è _non_ scalabile in quanto tutti i risultati di tutti i set di risultati saranno in memoria. Il metodo più appropriato/scalabile è quello di iterare su un 'SqlDataReader' e restituire ogni riga man mano che viene letta da' SqlDataReader'. @ La risposta di DanRadu qui, al di fuori di non gestire tutti i tipi di dati (una soluzione a breve scadenza), invia ogni riga man mano che viene letta: http://stackoverflow.com/questions/6388489/insert-into-temp-table-from-a -stored-procedure-che-torna-a più insiemi di risultati-/ 11045189 # 11045189 –

5

C'è un kludge che si può fare pure. Aggiungi un parametro opzionale N int al tuo sproc. Predefinito il valore di N a -1. Se il valore di N è -1, allora esegui ognuno dei tuoi selezionati. Altrimenti, fai l'ennesima selezione e solo l'ennesima selezione.

Per esempio,

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

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

I chiamanti del vostro sProc che non specificano N otterrà un set di risultati con più di un tabelle. Se devi estrarre una o più di queste tabelle da un altro sproc, chiama semplicemente il tuo sproc specificando un valore per N. Dovrai chiamare lo sproc una volta per ogni tabella che desideri estrarre. Inefficiente se hai bisogno di più di una tabella dal set di risultati, ma funziona in puro TSQL.