Am un proc spGetSites stocat care returnează trei coloane pentru SiteName, SiteId și UnitCount. Proc stocat funcționează perfect. „Încerc să stochez rezultatele procesului stocat într-un tabel temporar @Site pentru a-l folosi pentru raportul meu cu sintaxa de mai jos. De data aceasta am primit un mesaj de eroare:” Instrucțiunea INSERT EXEC nu poate fi imbricată „
Nu pot folosi instrucțiunea INSERT și EXEC în același timp?
DECLARE @Site TABLE (SiteName VARCHAR(100), SiteId INT, UnitCount INT) INSERT INTO @Site EXEC spGetSites @SiteId = 0
Comentarii
- Ar trebui , dbfiddle.uk/… Vă rugăm să adăugați procedura stocată la întrebare și etichetați versiunea SQL Server.
Răspuns
Dacă te uiți la codul pentru spGetSites
procedura, undeva în această procedură este un alt INSERT...EXEC
. Poate fi direct în această procedură sau cuibărit în intestinele altei proceduri pe care le numește.
În cele din urmă, dacă o procedură stocată folosește INSERT...EXEC
atunci dacă încercați să apelați această procedură stocată în contextul altei INSERT...EXEC
veți primi eroarea văzând .
Cum o remediați?
-
Puteți pur și simplu să luați
INSERT...EXEC
interior și să introduceți codul în acest sens singură procedură stocată. Totuși, bănuiesc că ar putea exista o altă procedură dintr-un motiv: adică să păstrezi codul DRY. -
Deoarece acesta este un
Get
procedură, sperăm că nu există manipulări de date nicăieri în stiva de apeluri. Puteți converti procedura copil într-o funcție cu valoare de tabel. Acest lucru vă va permite să convertiți aceaINSERT...EXEC
într-unINSERT...SELECT
și rezolvați această problemă. -
Utilizați tabele temp cu scop la procedura externă pentru a transmite date între proceduri. Această soluție primește complicat, deci nu este preferatul meu și, în general, descurajez acest tipar atunci când există o opțiune mai bună – dar, din motive de completitudine, îl voi include aici. Practic, dacă creați tabelul #temp în afara
spGetSites
îl puteți utiliza în interiorulspGetSites
(fără a-l crea în interiorul acestuia) și al tabelului cu datele inserate va supraviețui executării procedurii și va continua să funcționeze.
Nu-mi place opțiunea 3, deoarece este un model de codare suficient de complex pentru a asigura că cineva o încurcă în viitor, cu excepția cazului în care toată lumea este la bord și este familiarizată cu codarea model: * spGetSites
va eșua dacă nu creați mai întâi tabelul. Toți apelanții trebuie să-și amintească pentru a crea tabelul exact la fel mai întâi. * spGetSites
nu poate presupune că tabelul este gol. Este posibil să aibă date existente din apelul extern (sau o execuție anterioară de la același apelant) * Depanare și depanare (și chiar obținerea unui plan de interogare) pentru spGetSites
este mai complex din cauza confuziei de creare a tabelelor.
Ce aș face?
Fără a ști cât de complex este codul se află în spatele spGetSites
, aș căuta să creez un TVF în linie care să înlocuiască INSERT...EXEC
interior cu INSERT...SELECT
sau, eventual, toate spGetSites
ar putea fi simplificate / rescrise pentru a fi conținute în sine fără INSERT...EXEC