2008-09-12 15 views
36

Używam SQL Server 2005, i chciałbym wiedzieć, jak uzyskać dostęp do różnych zestawów wyników z wewnątrz transakcji-sql. Poniższa procedura składowana zwraca dwa zestawy wyników, w jaki sposób uzyskać do nich dostęp, na przykład z innej procedury składowanej?Dostęp do zestawów wyników z poziomu procedur przechowywanych 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 

Potrzebuję być w stanie iterować przez oba zestawy wyników indywidualnie.

EDYCJA: Tylko w celu wyjaśnienia pytania, chcę przetestować procedur przechowywanych. Mam zestaw procedur składowanych, które są używane z klienta VB.NET, które zwracają wiele zestawów wyników. Nie zostaną one zmienione na funkcję wycenianą w tabeli, w rzeczywistości nie mogę zmienić procedur. Zmiana procedury nie jest opcją.

Zestawy wyników zwrócone przez procedury nie są tymi samymi typami danych ani liczbą kolumn.

Odpowiedz

34

Krótka odpowiedź brzmi: nie możesz tego zrobić.

Z poziomu T-SQL nie ma możliwości uzyskania dostępu do wielu wyników zagnieżdżonego wywołania procedury składowanej, bez zmiany procedury składowanej, jak sugerowali inni.

Aby być kompletne, jeżeli procedura wracali pojedynczy wynik, można wstawić je do tabeli temp lub zmiennej tabeli z następującą składnią:

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

można wykorzystać taką samą składnię procedury, które zwraca wiele wyników, ale przetwarza tylko pierwszy wynik, reszta zostanie odrzucona.

+2

Właśnie przetestowałem rozwiązanie Brannona, a właściwie, jeśli wszystkie zapytania w procedurze zwanej procedurą przechowywaną zwrócą tę samą liczbę kolumn i typów danych, zestaw wyników zwrócony będzie składał się z zestawów wyników. Co jest prawie bezużyteczne. Dzięki za pomoc. –

0

Można wybrać je do tabel tymczasowych lub napisać funkcje z wartościami tabel, aby zwrócić zestawy wyników. Pytają, jak iterować przez zestawy wyników?

1

Można to łatwo zrobić na dwa sposoby. Albo przyklej wyniki do tabeli temp, a następnie odwołaj się do tabeli temp z twojego sproc. Inną alternatywą jest umieszczenie wyników w zmiennej XML, która jest używana jako zmienna OUTPUT.

Istnieją jednak plusy i minusy dla obu tych opcji. W przypadku tabeli tymczasowej musisz dodać kod do skryptu, który tworzy procedurę wywołującą, aby utworzyć tabelę tymczasową przed zmodyfikowaniem procedury. Powinieneś również wyczyścić tabelę tymczasową po zakończeniu procedury.

Dzięki XML może wymagać dużej ilości pamięci i wolniej.

4

Należy zauważyć, że istnieje dodatkowe, nieudokumentowane ograniczenie dla instrukcji INSERT INTO ... EXEC: nie można jej zagnieździć. Oznacza to, że zapisany proces, który wywołuje EXEC (lub jakikolwiek, który wywołuje po kolei) sam nie może wykonać INSERT INTO ... EXEC. Wygląda na to, że istnieje pojedynczy scratchpad na proces, który gromadzi wynik, a jeśli są zagnieżdżone, dostaniesz błąd, gdy dzwoniący otworzy to, a następnie osoba próbująca otworzy ponownie.

Matthieu, musisz zachować oddzielne tabele tymczasowe dla każdego "typu" wyniku. Ponadto, jeśli wykonujesz tę samą funkcję wiele razy, może być konieczne dodanie dodatkowej kolumny do tego wyniku, aby wskazać, z którego połączenia wynika.

2

Niestety nie można tego zrobić. Problem polega oczywiście na tym, że nie ma żadnej składni SQL, która by to umożliwiła. Zdarza się, że "pod maską" oczywiście, ale nie można uzyskać tych innych wyników w TSQL, tylko z aplikacji za pośrednictwem ODBC lub cokolwiek innego.

Jest na to sposób, podobnie jak w większości rzeczy. Sztuką jest użycie automatyzacji ole w TSQL w celu utworzenia obiektu ADODB, który po kolei otwiera każdy zestaw wyników i zapisuje wyniki w tabelach, które nominujesz (lub robisz, co chcesz z zestawami wyników). możesz też zrobić to w DMO, jeśli lubisz ból.

8

Z łatwością mogłem to zrobić, tworząc procedurę składowaną CLR SQL2005, która zawierała wewnętrzny zestaw danych.

Nowy dodatek SqlDataAdapter sprawi, że sproc z wieloma wynikami zostanie domyślnie ustawiony na zbiór danych z wieloma tabelami. Dane w tych tabelach mogą z kolei zostać wstawione do tabel #Temp w wywołującym sprocu, który chcesz napisać. dataset.ReadXmlSchema pokaże schemat każdego zestawu wyników.

Krok 1: Rozpocznij pisanie sproc który odczyta dane z wielu wyników ustawiony sproc

a. Utwórz oddzielną tabelę dla każdego zestawu wyników zgodnie ze schematem.

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. W tym momencie może trzeba zadeklarować kursor powtarzalnie dzwonić CLR sproc można utworzyć tutaj:

Krok 2: Dodać CLR sproc

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

    End Sub 
End Class 

a. Połącz za pomocą New SqlConnection("context connection=true").

b. Ustaw obiekt polecenia (cmd), aby zawierał sproc z wieloma wynikami.

c. Uzyskaj wszystkie dane, korzystając z:

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. Iteruj po każdej tabeli i wstaw każdy wiersz do odpowiedniej tabeli tymczasowej (utworzonej w kroku pierwszym powyżej).

Ostatnia uwaga: Z mojego doświadczenia wynika, możesz wymusić pewne relacje między tabel więc wiesz, które partia każdy rekord pochodzi.

To wszystko, co było do tego!

~ Shaun, w pobliżu Seattle

+0

Chociaż SQLCLR jest jedynym sposobem na rozwiązanie tego problemu, przejście łatwej drogi wyrzucania do 'DataSet' jest _nie_ skalowalne, ponieważ wszystkie wyniki ze wszystkich zestawów wyników będą w pamięci. Bardziej odpowiednią/skalowalną metodą jest iteracja na 'SqlDataReader' i zwrócenie każdego wiersza, jak to jest odczytywane z' SqlDataReader'. Odpowiedź @ DanRadu tutaj, poza nieprzydzielaniem wszystkich typów danych (zwarciem, które można naprawić), wysyła każdy wiersz w następującej postaci: http://stackoverflow.com/questions/6388489/insert-into-temp-table-from-a -stored-procedura-że-zwraca-wiele-zestawów-wyników/11045189 # 11045189 –

5

Jest kludge że można to zrobić również. Dodaj opcjonalny parametr N int do sproc. Domyślnie wartość od N do -1. Jeśli wartość N wynosi -1, wykonaj wszystkie wybrane ustawienia. W przeciwnym razie wykonaj N-ty wybierz i tylko N-ty wybierz.

Na przykład

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

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

Rozmówcy Twojego sproc nie określi N dostanie zestaw wyników z więcej niż jednej tabeli. Jeśli potrzebujesz wyodrębnić jedną lub więcej tabel z innego sproc, po prostu wywołaj sproc określając wartość dla N. Musisz wywołać sproc jeden raz dla każdej tabeli, którą chcesz wyodrębnić. Nieefektywne, jeśli potrzebujesz więcej niż jednej tabeli z zestawu wyników, ale działa ona w czystym TSQL.