Ho un proc spGetSites memorizzato che restituisce tre colonne per SiteName, SiteId e UnitCount. Il processo memorizzato funziona perfettamente. Sto cercando di memorizzare i risultati della procedura memorizzata in una tabella temporanea @Site da utilizzare per il mio rapporto con la sintassi seguente. Questa volta ho ricevuto un messaggio di errore: “Listruzione INSERT EXEC non può essere annidata”
Non posso utilizzare le istruzioni INSERT e EXEC contemporaneamente?
DECLARE @Site TABLE (SiteName VARCHAR(100), SiteId INT, UnitCount INT) INSERT INTO @Site EXEC spGetSites @SiteId = 0
Commenti
- Dovresti , dbfiddle.uk/… Aggiungi la procedura memorizzata alla domanda e tagga la tua versione di SQL Server.
Risposta
Se guardi il codice del tuo spGetSites
, da qualche parte in quella procedura cè un altro INSERT...EXEC
. Potrebbe essere direttamente in quella procedura, o annidato nelle viscere di qualche altra procedura che chiama.
In definitiva, se una procedura memorizzata utilizza INSERT...EXEC
, se provi a chiamare quella procedura memorizzata nel contesto di unaltra INSERT...EXEC
riceverai lerrore che sei vedendo .
Come risolverlo?
-
Potresti semplicemente prendere il
INSERT...EXEC
interno e incorporare il codice a questo procedura memorizzata unica. Tuttavia, sospetto che ci sia unaltra procedura per un motivo: ad esempio per mantenere il codice ASCIUTTO. -
Poiché questo è un
Get
, si spera che non avvenga alcuna manipolazione dei dati da nessuna parte nello stack di chiamate. È possibile convertire la procedura figlia in una funzione con valori di tabella. Ciò consentirebbe di convertire quellaINSERT...EXEC
interna in unINSERT...SELECT
e risolvere il problema. -
Utilizza le tabelle temporanee con ambito per la procedura esterna per passare i dati tra le procedure. Questa soluzione ottiene complicato, quindi non è il mio preferito, e generalmente sconsiglio questo schema quando cè “unopzione migliore – ma per completezza, lo includerò qui. Fondamentalmente, se crei la tua tabella #temp allesterno di
spGetSites
puoi usarla allinterno dispGetSites
(senza crearla allinterno) e la tabella con i dati inseriti sopravviverà allesecuzione della procedura e continuerà a funzionare.
Non mi piace lopzione 3 perché è uno schema di codifica abbastanza complesso da garantire che qualcuno lo incasini in futuro, a meno che tutti non siano daccordo e abbiano familiarità con la codifica pattern: * spGetSites
non funzionerà a meno che non crei prima la tabella. Tutti i chiamanti devono ricordarsi di creare prima la tabella esattamente la stessa. * spGetSites
non può “presumere che la tabella sia vuota. Potrebbe avere dati esistenti dalla chiamata esterna (o unesecuzione precedente dallo stesso chiamante) * Risoluzione dei problemi e debug (e persino ottenere un piano di query) per spGetSites
è più complesso a causa della confusione nella creazione della tabella.
Cosa dovrei fare?
Senza sapere quanto sia complesso il il codice è dietro spGetSites
, vorrei “creare un TVF inline che sostituisca il INSERT...EXEC
interno con INSERT...SELECT
o possibilmente tutto spGetSites
potrebbe essere semplificato / riscritto per renderlo autonomo senza INSERT...EXEC