Jeg har en gemt proc spGetSites, der returnerer tre kolonner til SiteName, SiteId og UnitCount. Den lagrede proc kører helt fint. Jeg prøver at gemme resultaterne af den lagrede proc til en temp-tabel @Site til brug for min rapport med nedenstående syntaks. Denne gang fik jeg en fejlmeddelelse: “INSERT EXEC-sætning kan ikke indlejres”
Kan jeg ikke bruge INSERT- og EXEC-erklæringen på samme tid?
DECLARE @Site TABLE (SiteName VARCHAR(100), SiteId INT, UnitCount INT) INSERT INTO @Site EXEC spGetSites @SiteId = 0
Kommentarer
- Du skal , dbfiddle.uk/… Tilføj din gemte procedure til spørgsmålet, og tag din SQL Server-version.
Svar
Hvis du ser på koden til din spGetSites
procedure, et eller andet sted i denne procedure er en anden INSERT...EXEC
. Det kan være direkte i denne procedure eller indlejret i tarmene ved en anden procedure, det kalder.
I sidste ende Hvis en gemt procedure bruger INSERT...EXEC
så får du den fejl, du er, hvis du prøver at kalde den lagrede procedure i sammenhæng med en anden INSERT...EXEC
ser .
Hvordan løser du det?
-
Du kan simpelthen tage det indre
INSERT...EXEC
og integrere koden til dette enkelt lagret procedure. Jeg formoder dog, at en anden procedure kan være der af en grund: dvs. at holde din kode TØR. -
Da dette er en
Get
procedure, forhåbentlig sker der ingen datamanipulation overalt i opkaldstakken. Du kan konvertere barnproceduren til en tabelværdifunktion. Dette giver dig mulighed for at konvertere den indreINSERT...EXEC
i enINSERT...SELECT
og løse dette problem. -
Brug temp-tabeller, der er omfattet af den ydre procedure for at videregive data mellem procedurer. Denne løsning får kompliceret, så det er ikke min favorit, og jeg fraråder mig generelt dette mønster, når der er en bedre mulighed – men for fuldstændighedens skyld vil jeg inkludere det her. Dybest set, hvis du opretter din #temp-tabel uden for
spGetSites
, kan du bruge den inde ispGetSites
(uden at oprette den derinde), og tabellen med indsatte data vil overleve procedurens udførelse og fortsætte med at arbejde.
Jeg kan ikke lide valgmulighed 3, fordi det er et kodemønster, der er så komplekst, at det sikres, at nogen ødelægger det i fremtiden, medmindre alle er om bord og kender kodningen mønster: * spGetSites
mislykkes, medmindre du opretter tabellen først. Alle opkaldere skal huske at oprette tabellen nøjagtigt den samme først. * spGetSites
kan ikke antage, at tabellen er tom. Den kan have eksisterende data fra det ydre opkald (eller en tidligere udførelse fra den samme opkalder) * Fejlfinding og fejlretning (og endda få en forespørgselsplan) for spGetSites
er mere kompleks på grund af forvirring af tabeloprettelsen.
Hvad ville jeg gøre?
Uden at vide, hvor kompleks den koden er bag spGetSites
, jeg ser på at oprette en indbygget TVF, der erstatter den indre INSERT...EXEC
med INSERT...SELECT
eller muligvis hele spGetSites
kunne forenkles / omskrives for at gøre det selvstændigt uden INSERT...EXEC