Mam zapisaną procedurę spGetSites, która zwraca trzy kolumny dla SiteName, SiteId i UnitCount. Przechowywany proces działa doskonale. Próbuję zapisać wyniki zapisanego procesu w tabeli tymczasowej @Site do wykorzystania w raporcie z poniższą składnią. Tym razem otrzymałem komunikat o błędzie: „INSERT EXEC nie można zagnieżdżać”
Czy nie mogę używać instrukcji INSERT i EXEC w tym samym czasie?
DECLARE @Site TABLE (SiteName VARCHAR(100), SiteId INT, UnitCount INT) INSERT INTO @Site EXEC spGetSites @SiteId = 0
Komentarze
- Należy , dbfiddle.uk/… Dodaj procedurę składowaną do pytania i oznacz swoją wersję programu SQL Server.
Odpowiedź
Jeśli spojrzysz na kod swojego spGetSites
procedura, gdzieś w tej procedurze jest inna INSERT...EXEC
. Może być bezpośrednio w tej procedurze lub zagnieżdżona w trzewiach innej wywoływanej procedury.
Ostatecznie, jeśli procedura składowana używa INSERT...EXEC
, to jeśli spróbujesz wywołać tę procedurę składowaną w kontekście innego INSERT...EXEC
, pojawi się błąd, widzenie .
Jak to naprawić?
-
Możesz po prostu wziąć wewnętrzny
INSERT...EXEC
i wstawić do niego kod pojedyncza procedura składowana. Chociaż podejrzewam, że z jakiegoś powodu może istnieć inna procedura: np. Aby Twój kod był SUCHY. -
Ponieważ jest to
Get
, miejmy nadzieję, że nie ma żadnej manipulacji danymi w żadnym miejscu stosu wywołań. Możesz przekonwertować procedurę potomną na funkcję o wartości tabeli. Pozwoliłoby to przekonwertować wewnętrznąINSERT...EXEC
doINSERT...SELECT
i rozwiąż ten problem. -
Użyj tabel tymczasowych w zakresie zewnętrznej procedury, aby przekazywać dane między procedurami. To rozwiązanie pobiera skomplikowane, więc nie jest moim ulubionym i generalnie odradzam ten wzór, gdy istnieje lepsza opcja – ale ze względu na kompletność wstawię go tutaj. Zasadniczo, jeśli utworzysz swoją #temp tabelę poza
spGetSites
, możesz jej użyć wewnątrzspGetSites
(bez tworzenia jej w tym miejscu), a tabeli z wprowadzonymi danymi przetrwa wykonanie procedury i będzie kontynuować pracę.
Nie podoba mi się opcja 3, ponieważ jest to wzorzec kodowania na tyle złożony, że w przyszłości ktoś go zepsuje, chyba że wszyscy są na pokładzie i zaznajomieni z kodowaniem wzorzec: * spGetSites
zakończy się niepowodzeniem, chyba że najpierw utworzysz tabelę. Wszyscy dzwoniący muszą pamiętać, aby najpierw utworzyć tabelę dokładnie tak samo. * spGetSites
nie można założyć, że tabela jest pusta. Może zawierać istniejące dane z wywołania zewnętrznego (lub wcześniejszego wykonania od tego samego dzwoniącego) * Rozwiązywanie problemów i debugowanie (a nawet uzyskanie plan zapytań) dla spGetSites
jest bardziej złożony z powodu zamieszania przy tworzeniu tabeli.
Co bym zrobił?
Nie wiedząc, jak skomplikowany jest za kodem spGetSites
, chciałbym się zająć utworzeniem wbudowanego TVF, który zamieni wewnętrzny INSERT...EXEC
na INSERT...SELECT
lub prawdopodobnie wszystkie spGetSites
mogłyby zostać uproszczone / przepisane, aby były samodzielne bez INSERT...EXEC