locked
Guardar el resultado de un procedimiento almacenado en una tabla

    Question

  • Me gustaría saber cómo puedo hacer esto en SQL Server 2005

     

    insert into #t(producto, importe)

    exec dbo.MiProcedimientoAlmacenado

     

    La idea es que el mismo procedimiento lo llamo distintas veces y voy guardando el resultado en la tabla temporal #t

    Muchas gracias

    Monday, January 25, 2010 9:40 PM

Answers

  • Hola.

    Creo que estás de suerte, porque tiene un muy "fácil" arreglo. Debes crear un nuevo procedimiento que te devuelva, en un único recordset, lo que devuelve "ConsultaProcedimiento" para cada una de las empresas. Así, de un golpe, te quitas de en medio la tabla temporal y el cursor.

    Sobre cómo construir ese procedimiento, a las malas, debe hacer un "union all" de cada uno de los recordset de las otras empresas:

    "select de la consulta para @empresa1"
    union all
    "select de la consulta para @empresa2"
    union all
    "select de la consulta para @empresa3"

    También es posible que esta consulta de 3 pueda simplificarse. Habría que ver ese código para saberlo.


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Wednesday, January 27, 2010 10:22 AM
    Moderator

All replies

  • Hola
    Suponemos que el procedimiento "MiProcedimientoAlmacenado" hace un Select.
    Entonces la sentencia está bien:

    INSERT INTO #T (producto, importe) EXEC dbo.MiProcedimientoAlmacenado.

    O te refieres a otra cosa?

    Saludos
    Monday, January 25, 2010 10:13 PM
  • Hola.

    La sentencia está bien según la pones. Los únicos motivos por los que se me ocurre que puede estar fallando son:

    - La tabla temporal no está hecha a la medida del procedimiento almacenado. El procedimiento almacenado devuelve un recordset, pero no tiene el mismo número de columnas o las columnas no tienen los tipos adecuados.
    - El procedimiento ya realiza un insert.. exec en su interior. No es posible anidar esta sentencia, deben estar en paralelo o si no deberás buscar otro mecanismo para lograrlo.

    Si no es una de estas cosas, pon el mensaje de error que recibes.


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Tuesday, January 26, 2010 6:19 AM
    Moderator
  • La tabla temporal es correcta, adjunto error de SQL

    (0 filas afectadas)
    Mens 8164, Nivel 16, Estado 1, Procedimiento MiProcedimientoAlmacenado, Línea 42
    La instrucción INSERT EXEC no se puede anidar.

    Como lo puedo solucionar?

    He estado mirando procedimientosAlmacenados con parametros OUTPUT, pero no puedo poner una tabla en output..

    Gracias por vuestros comentarios.

    Saludos

    Tuesday, January 26, 2010 10:57 AM
  • Tal y como te comentaba Alberto en su respuesta, ese procedimiento almacenado hace algo más que una simple SELECT

    Tuesday, January 26, 2010 11:04 AM
  • qwalgrande dixit:

    - El procedimiento ya realiza un insert.. exec en su interior. No es posible anidar esta sentencia, deben estar en paralelo o si no deberás buscar otro
    mecanismo para lograrlo.

    Que mecanismo puedo utilizar para lograrlo??

    Tines razon Carlos, MiProcedimientoAlmacenado no es una simple SELECT. Hay distintas selects, variables y una tabla temporal...

    Gracias
    Tuesday, January 26, 2010 11:35 AM
  • Hola.

    Pásanos el código, a ver qué puede hacerse.


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Tuesday, January 26, 2010 11:46 AM
    Moderator
  • ¿No puedes poner la lógica dentro del procedimiento almacenado? Es decir, crear la tabla temporal, dentro del procedimiento comprobar que existe la tabla temporal y, en caso positivo, insertar los datos en ella.

    Es decir, algo como
    USE AdventureWorks
    GO
    
    CREATE PROC proc_test
    AS
    BEGIN
    	  
          SELECT  LoginID
          FROM    HumanResources.Employee
          
          
          IF OBJECT_ID ( '#t' ) IS NOT NULL
             BEGIN
                   INSERT  #t
                           SELECT  LoginID
                           FROM    HumanResources.Employee
             END
    END
          
    GO      
    CREATE TABLE #t( l varchar(1000) )
    
    INSERT  #t
            EXEC proc_test
    
    SELECT * FROM #t
    Tuesday, January 26, 2010 11:49 AM
  • Gracias Carlos, pero no me sirve.

    Me  explico un poco mejor para ver si podemos encontrar solución. 

    Tengo la misma estructura de tablas en tres servidores distintos. las vamos a llamar BD1, BD2 y BD3. 

    La idea es tener una consulta que sirva para las tres bases de datos, para no tener que mantener el código por triplicado..

    Con lo que todos los ProcedimientosAlmacenados reciben un parámetro indicando sobre qué base de datos quiero obtener la información.

    Hasta aquí funciona perfectamente.

     

    El problema lo tengo cuando en el ComboBox que puedo elegir la Base de Datos, quiero una opción que sea TODAS. (Esta opción como su nombre indica, debe consultar los datos de BD1, BD2 y BD3)

    Para realizar esto he creado un nuevo procedimiento Almacenado proc_con_TODAS @Empresa

    IF @Empresa <> 'TODAS'

                BEGIN

                      EXEC [ConsultaProcedimiento] @Empresa

                END

          ELSE

                BEGIN

                                   Create Table #T (producto varchar(120), cantidad int)

                          Declare @Empresa2 varchar(250)

                            Tengo un cursor que recorre las tres BD.

                            Actualizo el campo  @Empresa2 (Base de datos que estoy consultando)

                           

                        INSERT INTO #T (producto, cantidad)

                        EXEC [ConsultaProcedimiento] @Empresa2 

                                   END

     

    Si en este código no pongo la sentencia (INSERT INTO #T (producto, cantidad)) al ejecutar el informe me sale el resultado en tres bloques. Lo que quiero es guardarlo de forma temporal en una tabla para mostrar todo el resultado junto.

     

    Muchas gracias por vuestra ayuda.

    Un Saludo

    Tuesday, January 26, 2010 7:51 PM
  • Hola.

    Creo que estás de suerte, porque tiene un muy "fácil" arreglo. Debes crear un nuevo procedimiento que te devuelva, en un único recordset, lo que devuelve "ConsultaProcedimiento" para cada una de las empresas. Así, de un golpe, te quitas de en medio la tabla temporal y el cursor.

    Sobre cómo construir ese procedimiento, a las malas, debe hacer un "union all" de cada uno de los recordset de las otras empresas:

    "select de la consulta para @empresa1"
    union all
    "select de la consulta para @empresa2"
    union all
    "select de la consulta para @empresa3"

    También es posible que esta consulta de 3 pueda simplificarse. Habría que ver ese código para saberlo.


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Wednesday, January 27, 2010 10:22 AM
    Moderator
  • Gracias qwalgrande por tu ayuda,

    Es verdad que con UNIONS podemos concatenar distintas empresas.

    Pero si en lugar de 3 empresas son 20... Mantener el código se complica bastante...

    Si no tengo otra solución creo que tendré que hacer lo que tu me dices... pero esta es mi ultima opción.

     

    No existe ninguna fórmula para poder hacer esto??

                        INSERT INTO #T (producto, cantidad)

                 EXEC [ConsultaProcedimiento] @Empresa2 

     

    Teniendo en cuenta que el ConsultaProcedimiento tiene una tabla temporal en su interior.

    Perdona que no adjunte el contenido de ConsultaProcedimiento, ya que en mi opinión el problema no es el procedimiento ConsultaProcedimiento, sino la forma de llamar el mismo procedimiento n veces.

    Muchas gracias.

    Wednesday, January 27, 2010 7:38 PM
  • Hola.

    Pues no. Como te dice el mensaje de error, no puedes anidar dos insert .. exec. Pero lo que tú ves como un problema de mantenimiento (algo que no entiendo, lo comento más abajo), yo lo veo como un problema de rendimiento si lo haces del otro modo, ya que creas dos tablas temporales que no necesitas.

    En cuanto al problema de mantenimiento, si la consulta es la misma para todas las empresas, salvo algún parámetro, alguna base de datos que cambie, etc., en tiempo es algo que no es nada costoso. Si el proceso en general lee de varios servidores de bases de datos, plantéate utilizar un paquete de integration services para realizar ese volcado desde todas las empresas.


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Wednesday, January 27, 2010 8:53 PM
    Moderator
  • Muchas gracias por vuestra ayuda,

    Tienes razón, voy a utilizar la solución de los UNION.

    Por otro lado empezaré a mirar los paquetes de Integration Services. No conozco estos paquetes.

    Sabes donde puedo encontrar algún manual para empezar des de cero?

    Un Saludo.

    Wednesday, January 27, 2010 9:39 PM
  • Hola.

    Haz los tutoriales de los Books Online. Te paso el link de los de SSIS 2005: http://msdn.microsoft.com/es-es/library/ms167031(SQL.90).aspx.


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Thursday, January 28, 2010 8:25 AM
    Moderator