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ć?

  1. 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.

  2. 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 do INSERT...SELECT i rozwiąż ten problem.

  3. 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ątrz spGetSites (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

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *