Jag har en lagrad proc spGetSites som returnerar tre kolumner för SiteName, SiteId och UnitCount. Den lagrade proc fungerar helt bra. Jag försöker lagra resultaten av den lagrade proc till en temp-tabell @Site för att använda för min rapport med nedanstående syntax. Den här gången fick jag ett felmeddelande: ”INSERT EXEC-uttalande kan inte kapslas”

Kan jag inte använda INSERT- och EXEC-uttalanden samtidigt?

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

Kommentarer

  • Du borde , dbfiddle.uk/… Lägg till den lagrade proceduren i frågan och märka din SQL Server-version.

Svar

Om du tittar på koden för din spGetSites förfarande, någonstans i det förfarandet är en annan INSERT...EXEC. Det kan vara direkt i det förfarandet, eller kapslat i tarmarna av någon annan procedur som det kallar.

I slutändan, om en lagrad procedur använder INSERT...EXEC, om du försöker ringa den lagrade proceduren i samband med en annan INSERT...EXEC får du det fel du är seende .

Hur fixar du det?

  1. Du kan helt enkelt ta det inre INSERT...EXEC och infoga koden till detta enkel lagrad procedur. Men jag misstänker att andra procedurer kan finnas där av en anledning: dvs att hålla din kod TORR.

  2. Eftersom det här är en Get procedur, förhoppningsvis finns det ingen datahantering någonstans i samtalsstacken. Du kan konvertera barnproceduren till en tabellvärderad funktion. Detta gör att du kan konvertera den inre INSERT...EXEC till en INSERT...SELECT och lösa problemet.

  3. Använd temp-tabeller som omfattas av den yttre proceduren för att skicka data mellan procedurerna. Denna lösning blir komplicerat, så det är inte min favorit, och jag avskräcker i allmänhet detta mönster när det finns ett bättre alternativ – men för fullständighetens skull tar jag det här. I grund och botten, om du skapar din #temp-tabell utanför spGetSites kan du använda den i spGetSites (utan att skapa den där inne), och tabellen med inlagda data kommer att överleva procedurutförandet och fortsätta att arbeta.

Jag gillar inte alternativ 3 eftersom det är ett kodningsmönster som är tillräckligt komplext för att säkerställa att någon förstör det i framtiden, såvida inte alla är ombord och bekanta med kodningen mönster: * spGetSites misslyckas om du inte skapar tabellen först. Alla som ringer måste komma ihåg att skapa tabellen exakt samma först. * spGetSites kan inte anta att tabellen är tom. Den kan ha befintlig data från det yttre samtalet (eller en tidigare körning från samma uppringare) * Felsökning och felsökning (och till och med få en frågeplan) för spGetSites är mer komplex på grund av tabellskapande förvirring.

Vad skulle jag göra?

Utan att veta hur komplex den koden ligger bakom spGetSites, jag skulle se till att skapa en inbyggd TVF som ersätter den inre INSERT...EXEC med INSERT...SELECT eller eventuellt hela spGetSites kan förenklas / skrivas om för att göra det fristående utan INSERT...EXEC

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *