Ik heb een opgeslagen proc spGetSites die drie kolommen retourneert voor SiteName, SiteId en UnitCount. De opgeslagen procedure werkt prima. Ik probeer de resultaten van het opgeslagen proces op te slaan in een tijdelijke tabel @Site om te gebruiken voor mijn rapport met onderstaande syntaxis. Deze keer kreeg ik een foutmelding: “INSERT EXEC-instructie kan niet worden genest”

Kan ik de instructie INSERT en EXEC niet tegelijkertijd gebruiken?

DECLARE @Site TABLE (SiteName VARCHAR(100), SiteId INT, UnitCount INT) INSERT INTO @Site EXEC spGetSites @SiteId = 0 

Reacties

  • Je moet , dbfiddle.uk/… Voeg je opgeslagen procedure toe aan de vraag en tag je SQL Server-versie.

Antwoord

Als je kijkt naar de code voor je spGetSites procedure, ergens in die procedure is een andere INSERT...EXEC. Het kan direct in die procedure zitten, of genesteld in de ingewanden van een andere procedure die het aanroept.

Uiteindelijk, als een opgeslagen procedure INSERT...EXEC gebruikt, dan als je die opgeslagen procedure probeert aan te roepen in de context van een andere INSERT...EXEC, krijg je de fout die je bent zien

Hoe repareer je het?

  1. Je zou eenvoudig de innerlijke INSERT...EXEC kunnen nemen en de code hierop inline kunnen zetten enkele opgeslagen procedure. Hoewel ik vermoed dat er een andere procedure is om een reden: dat wil zeggen om je code DROOG te houden.

  2. Omdat dit een Get procedure, hopelijk vindt er nergens in de aanroepstapel gegevensmanipulatie plaats. U zou de onderliggende procedure kunnen converteren naar een tabelwaardefunctie. Hiermee kunt u die innerlijke INSERT...EXEC in een INSERT...SELECT en los dit probleem op.

  3. Gebruik temp-tabellen met een bereik tot de buitenste procedure om gegevens tussen procedures door te geven. Deze oplossing krijgt gecompliceerd, dus het is niet mijn favoriet, en ik raad dit patroon over het algemeen af als er een betere optie is – maar voor de volledigheid zal ik het hier opnemen. Kortom, als u uw #temp-tabel buiten spGetSites maakt, kunt u deze binnen spGetSites gebruiken (zonder deze daarbinnen te maken), en de tabel met ingevoerde gegevens zal de uitvoering van de procedure overleven en blijven werken.

Ik hou niet van optie 3 omdat het een coderingspatroon is dat complex genoeg is om ervoor te zorgen dat iemand het in de toekomst verknoeit, tenzij iedereen aan boord is en bekend is met de codering patroon: * spGetSites zal mislukken, tenzij u eerst de tabel maakt. Alle bellers moeten onthouden om de tabel eerst exact hetzelfde te maken. * spGetSites kan “niet aannemen dat de tabel leeg is. Het kan bestaande gegevens bevatten van de externe aanroep (of een eerdere uitvoering van dezelfde beller) * Probleemoplossing en foutopsporing (en zelfs een queryplan) voor spGetSites is complexer vanwege verwarring bij het maken van tabellen.

Wat zou ik doen?

Zonder te weten hoe complex de code achter spGetSites, ik “zou gaan kijken naar het maken van een inline TVF die de binnenste INSERT...EXEC vervangt door INSERT...SELECT of mogelijk alle spGetSites kunnen worden vereenvoudigd / herschreven om het zelfstandig te maken zonder de INSERT...EXEC

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *