Tengo un proc spGetSites almacenado que devuelve tres columnas para SiteName, SiteId y UnitCount. El proceso almacenado funciona perfectamente bien. Estoy tratando de almacenar los resultados del proceso almacenado en una tabla temporal @Site para usar en mi informe con la siguiente sintaxis. Esta vez recibí un mensaje de error: «La instrucción INSERT EXEC no se puede anidar»

¿No puedo usar la instrucción INSERT y EXEC al mismo tiempo?

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

Comentarios

  • Debería , dbfiddle.uk/… Agregue su procedimiento almacenado a la pregunta y etiquete su versión de SQL Server.

Respuesta

Si miras el código de tu spGetSites procedimiento, en algún lugar de ese procedimiento hay otro INSERT...EXEC. Puede estar directamente en ese procedimiento, o anidado en las entrañas de algún otro procedimiento al que llama.

En última instancia, si un procedimiento almacenado usa INSERT...EXEC, entonces si intenta llamar a ese procedimiento almacenado en el contexto de otro INSERT...EXEC obtendrá el error que está vidente .

¿Cómo se soluciona?

  1. Simplemente puede tomar el INSERT...EXEC interno e insertar el código en este procedimiento almacenado único. Sin embargo, sospecho que puede haber otro procedimiento por una razón: es decir, para mantener su código SECO.

  2. Dado que este es un Get procedimiento, con suerte no hay manipulación de datos en ninguna parte de la pila de llamadas. Puede convertir el procedimiento hijo en una función con valores de tabla. Esto le permitiría convertir ese INSERT...EXEC interno en un INSERT...SELECT y resuelva este problema.

  3. Use tablas temporales dentro del ámbito del procedimiento externo para pasar datos entre procedimientos. Esta solución obtiene complicado, por lo que no es mi favorito, y generalmente desaconsejo este patrón cuando hay una mejor opción, pero en aras de la integridad, lo incluiré aquí. Básicamente, si crea su tabla #temp fuera de spGetSites, puede usarla dentro de spGetSites (sin crearla allí dentro), y la tabla con datos insertados sobrevivirá a la ejecución del procedimiento y continuará funcionando.

No me gusta la opción 3 porque es un patrón de codificación lo suficientemente complejo como para asegurar que alguien lo arruine en el futuro, a menos que todos estén a bordo y familiarizados con la codificación patrón: * spGetSites fallará a menos que cree la tabla primero. Todas las personas que llaman deben recordar crear la tabla exactamente igual primero. * spGetSites no puede «asumir que la tabla está vacía. Podría tener datos existentes de la llamada externa (o una ejecución previa del mismo llamador) * Solución de problemas y depuración (e incluso obtener un plan de consulta) para spGetSites es más complejo debido a la confusión de creación de la tabla.

¿Qué haría?

Sin saber qué tan complejo es el código está detrás de spGetSites, buscaría crear un TVF en línea que reemplace el INSERT...EXEC interno con INSERT...SELECT o posiblemente todo spGetSites podría simplificarse / reescribirse para hacerlo autónomo sin INSERT...EXEC

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *