Jeg har en lagret proc spGetSites som returnerer tre kolonner for SiteName, SiteId og UnitCount. Den lagrede prosessen går helt greit. Jeg prøver å lagre resultatene av den lagrede proc til en temp-tabell @ Site for å bruke for rapporten min med syntaksen nedenfor. Denne gangen fikk jeg en feilmelding: «INSERT EXEC statement kan ikke nestes»
Kan jeg ikke bruke INSERT- og EXEC-setning samtidig?
DECLARE @Site TABLE (SiteName VARCHAR(100), SiteId INT, UnitCount INT) INSERT INTO @Site EXEC spGetSites @SiteId = 0
Kommentarer
- Du bør , dbfiddle.uk/… Vennligst legg til den lagrede prosedyren i spørsmålet, og merk SQL Server-versjonen din.
Svar
Hvis du ser på koden for spGetSites
prosedyre, et eller annet sted i den prosedyren er en annen INSERT...EXEC
. Det kan være direkte i den prosedyren, eller nestet i tarmene til en annen prosedyre det kaller.
Til slutt, hvis en lagret prosedyre bruker INSERT...EXEC
, så hvis du prøver å ringe den lagrede prosedyren i sammenheng med en annen INSERT...EXEC
, får du feilen du er ser .
Hvordan fikser du det?
-
Du kan ganske enkelt ta det indre
INSERT...EXEC
og legge koden inn i dette enkelt lagret prosedyre. Selv om jeg mistenker at en annen prosedyre kan være der av en grunn: dvs. å holde koden din TØRR. -
Siden dette er en
Get
prosedyre, forhåpentligvis skjer det ingen datamanipulering noe sted i samtalestakken. Du kan konvertere barneprosedyren til en tabellverdig funksjon. Dette gjør at du kan konvertere den indreINSERT...EXEC
til enINSERT...SELECT
og løse dette problemet. -
Bruk temp-tabeller som er rettet mot den ytre prosedyren for å overføre data mellom prosedyrene. Denne løsningen blir komplisert, så det er ikke min favoritt, og jeg fraråder generelt dette mønsteret når det er et bedre alternativ – men for fullstendighetens skyld vil jeg inkludere det her. I utgangspunktet, hvis du oppretter #temp-tabellen din utenfor
spGetSites
, kan du bruke den inne ispGetSites
(uten å lage den der inne), og tabellen med innlagte data vil overleve prosedyren og fortsette å jobbe.
Jeg liker ikke alternativ 3 fordi det er et kodemønster som er komplekst nok til å sikre at noen ødelegger det i fremtiden, med mindre alle er om bord og er kjent med kodingen mønster: * spGetSites
mislykkes med mindre du oppretter tabellen først. Alle innringere må huske å lage bordet nøyaktig det samme først. * spGetSites
kan ikke anta at tabellen er tom. Den kan ha eksisterende data fra den ytre samtalen (eller en tidligere utførelse fra samme innringer) * Feilsøking og feilsøking (og til og med få en spørringsplan) for spGetSites
er mer kompleks på grunn av tabellopprettingsforvirringen.
Hva ville jeg gjort?
Uten å vite hvor kompleks koden er bak spGetSites
, jeg ser på å lage en innebygd TVF som erstatter den indre INSERT...EXEC
med INSERT...SELECT
eller muligens alt spGetSites
kan forenkles / skrives om for å gjøre det selvforsynt uten INSERT...EXEC