none
CREAR TABLA TEMPORAL RRS feed

  • Pregunta

  • Hola os comento el problema que tengo.

    He creado un procedimiento en sql 2008 que es le siguiente. Como vereis abajo en el código he creado las variables que le paso por parámetros al procedimiento en visual studio 2010. Después, he creado una tabla temporal con los campos que me devuelve la consulta con la que relleno dicha tabla.

    Cuando meto este procedimiento en mi dataset de visual studio me dice lo siguiente:

    El asistente detectó los siguientes problemas al configurar el TableAdapter:

    Instruccion Select generada.

    El nombre de Objeto '#PrevioLA' no es valido.

    Yo nunca he creado tablas temporales así que no se por donde me puede venir el fallo.

    Esperando respuesta inmediata, me despido con un saludo.

    Charo.


    USE [CongeladosGalvez]
    GO
    /****** Object:  StoredProcedure [dbo].[TRANSACTSQL]    Script Date: 01/09/2015 10:42:10 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    -- Batch submitted through debugger: SQLQuery4.sql|7|0|C:\Users\Charo\AppData\Local\Temp\~vs2B0E.sql
    ALTER PROCEDURE [dbo].[TRANSACTSQL-1]
    (
        @FechaDesde date,
        @FechaHasta date,
        @arrRep varchar(max),
        @arrRuta varchar(max),
        @arrDia varchar(max),
        @arrIdFam varchar(max),
        @arrIdCatCli1 varchar(max),
        @arrIdCatCli2 varchar(max),
        @arrIdCatCli3 varchar(max),
        @arrIdCatCli4 varchar(max),
        @arrIdCatCli5 varchar(max),
        @arrIdCatArt1 varchar(max),
        @arrIdCatArt2 varchar(max),
        @arrIdCatArt3 varchar(max),
        @arrIdCatArt4 varchar(max),
        @arrIdCatArt5 varchar(max),
        @arrIdCatArt6 varchar(max)
    )
    AS
    create table #PrevioLA (
        IdAlbaran int ,
        FechaAlbaran date ,
        SerieNumero nvarchar(12) ,
        IdCliente int ,
        IdCentro nvarchar(5) ,
        IdArticulo nvarchar(10) ,
        CantidadVendida decimal(18, 5) ,
        PrecioVenta decimal(18, 5) ,
        ImporteVentaTotal decimal(18, 5) ,
        PrecioCoste decimal(18, 5) ,
        TarifaMinima decimal(18, 5) ,
        Tarifa1 decimal(18, 5) ,
        IdRepresentante int ,
        IdRepartidor int ,
        NombreCliente nvarchar(100) ,
        NombreArticulo nvarchar(80) ,
        IdFamiliaArticulo nvarchar(10) ,
        NombreFamiliaArticulo nvarchar(50) ,
        IdRutaVenta nvarchar(10) ,
        NombreRutaVenta nvarchar(150) ,
        IdRutaReparto nvarchar(10) ,
        NombreRutaReparto nvarchar(150) ,
        DiaSemana Tinyint ,
        NombreRepresentante nvarchar(70) ,
        IdSuperArticulo nvarchar(10) ,
        NombreSuperArticulo nvarchar(70) ,
        IdCategoriaCliente1 nvarchar(5) ,
        IdCategoriaCliente2 nvarchar(5) ,
        IdCategoriaCliente3 nvarchar(5) ,
        IdCategoriaCliente4 nvarchar(5) ,
        IdCategoriaCliente5 nvarchar(5) ,
        IdCategArticulo1 nvarchar(5) ,
        IdCategArticulo2 nvarchar(5) ,
        IdCategArticulo3 nvarchar(5) ,
        IdCategArticulo4 nvarchar(5) ,
        IdCategArticulo5 nvarchar(5) ,
        IdCategArticulo6 nvarchar(5) )
        
        BEGIN
        BEGIN TRANSACTION
    INSERT INTO #PrevioLA SELECT     dbo.LineasAlbaran.IdAlbaran, dbo.LineasAlbaran.FechaAlbaran, dbo.LineasAlbaran.SerieNumero, dbo.LineasAlbaran.IdCliente, dbo.LineasAlbaran.IdCentro,
                          dbo.LineasAlbaran.IdArticulo, dbo.LineasAlbaran.CantidadVendida, dbo.LineasAlbaran.PrecioVenta, dbo.LineasAlbaran.ImporteVenta, dbo.LineasAlbaran.PrecioCoste,
                          dbo.LineasAlbaran.TarifaMinima, dbo.LineasAlbaran.Tarifa1, dbo.LineasAlbaran.IdRepresentante, dbo.LineasAlbaran.IdRepartidor,
                          dbo.LineasAlbaran2.NombreCliente, dbo.LineasAlbaran2.NombreArticulo, dbo.LineasAlbaran2.IdFamiliaArticulo, dbo.LineasAlbaran2.NombreFamiliaArticulo,
                          dbo.LineasAlbaran2.IdRutaVenta, dbo.LineasAlbaran2.NombreRutaVenta, dbo.LineasAlbaran2.IdRutaReparto, dbo.LineasAlbaran2.NombreRutaReparto,
                          dbo.LineasAlbaran2.DiaSemana, dbo.LineasAlbaran2.NombreRepresentante, dbo.LineasAlbaran2.IdSuperArticulo, dbo.LineasAlbaran2.NombreSuperArticulo,
                          dbo.LineasAlbaran.IdCategoriaCliente1, dbo.LineasAlbaran.IdCategoriaCliente2, dbo.LineasAlbaran.IdCategoriaCliente3, dbo.LineasAlbaran.IdCategoriaCliente4,
                          dbo.LineasAlbaran.IdCategoriaCliente5, dbo.LineasAlbaran.IdCategArticulo1, dbo.LineasAlbaran.IdCategArticulo2, dbo.LineasAlbaran.IdCategArticulo3,
                          dbo.LineasAlbaran.IdCategArticulo4, dbo.LineasAlbaran.IdCategArticulo5, dbo.LineasAlbaran.IdCategArticulo6
    FROM         dbo.LineasAlbaran INNER JOIN
                          dbo.LineasAlbaran2 ON dbo.LineasAlbaran.IdAlbaran = dbo.LineasAlbaran2.IdAlbaran
    WHERE     (dbo.LineasAlbaran.FechaAlbaran >= @FechaDesde) AND (dbo.LineasAlbaran.FechaAlbaran <= @FechaHasta) AND (dbo.LineasAlbaran.IdRepresentante IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrRep) AS ArrayToTable_1))AND (dbo.LineasAlbaran2.IdRutaVenta  IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrRuta) AS ArrayToTable_1))AND (dbo.LineasAlbaran2.DiaSemana   IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrDia) AS ArrayToTable_1))AND (dbo.LineasAlbaran2.IdFamiliaArticulo    IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrIdFam ) AS ArrayToTable_1))AND (dbo.LineasAlbaran.IdCategoriaCliente1     IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrIdCatCli1  ) AS ArrayToTable_1))AND (dbo.LineasAlbaran.IdCategoriaCliente2     IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrIdCatCli2  ) AS ArrayToTable_1))AND (dbo.LineasAlbaran.IdCategoriaCliente3     IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrIdCatCli3  ) AS ArrayToTable_1))AND (dbo.LineasAlbaran.IdCategoriaCliente4     IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrIdCatCli4  ) AS ArrayToTable_1))AND (dbo.LineasAlbaran.IdCategoriaCliente5     IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrIdCatCli5  ) AS ArrayToTable_1))AND (dbo.LineasAlbaran.IdCategArticulo1      IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrIdCatart1  ) AS ArrayToTable_1))AND (dbo.LineasAlbaran.IdCategArticulo2      IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrIdCatart2  ) AS ArrayToTable_1))AND (dbo.LineasAlbaran.IdCategArticulo3      IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrIdCatart3  ) AS ArrayToTable_1))AND (dbo.LineasAlbaran.IdCategArticulo4      IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrIdCatart4  ) AS ArrayToTable_1))AND (dbo.LineasAlbaran.IdCategArticulo5      IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrIdCatart5  ) AS ArrayToTable_1))AND (dbo.LineasAlbaran.IdCategArticulo6      IN
                              (SELECT     StrVal
                                FROM          dbo.ArrayToTable(@arrIdCatart6  ) AS ArrayToTable_1))
                        
    END
        COMMIT TRANSACTION---END
     
        SELECT * FROM #PrevioLA
        SET NOCOUNT ON;


    Saluditos, Charo

    viernes, 9 de enero de 2015 10:33

Respuestas

  • Ese procedimiento almacenado se ejecutará más rápido sin la tabla temporal que con la tabla temporal.

    Las tablas temporales se alojan en la base de datos tempdb, no en memoria. Por otra parte en ese procedimiento creas una tabla temporal, luego se leen las tablas base, el resultado lo guardas en la tabla temporal, y luego lees la tabla temporal. ¿Cómo puede ser eso más rápido que leer sólo las tablas base?

    Créeme, llevo muchos años trabajando con SQL Server. La primera tabla temporal la cree con SQL Server 6.5 allá por los años noventa y tantos y sé lo que estoy diciendo.

    No digo que no uses nunca tablas temporales. Hay ciertos casos extremos en los que pueden aumentar el rendimiento, pero en la inmensa mayoría de ello, lo que hacen es todo lo contrario.



    Jesús López


    EntityLite a lightweight, database first, micro orm


    • Editado Jesús López viernes, 9 de enero de 2015 12:49 x
    • Marcado como respuesta charoeci1 viernes, 9 de enero de 2015 17:55
    viernes, 9 de enero de 2015 12:40
  • >>

    Por ello te consulto de que otra forma puedo gestionar tablas temporales sin utilzar table adapter.

    <<

    Puedes usar un SqlDataAdapter en vez de los table adapter. O puedes ejecutar el procedimiento con SqlCommand.ExecuteReader y cargar una lista de entidades a partir del DataReader devuelto. O puedes usar EntityLite para ejecutar el procedimiento y obtener una lista de entidades. O puedes usar Entity Framework o NHibernate, etc, etc.



    Jesús López


    EntityLite a lightweight, database first, micro orm

    • Marcado como respuesta charoeci1 viernes, 9 de enero de 2015 17:57
    viernes, 9 de enero de 2015 12:53

Todas las respuestas

  • >>

    Yo nunca he creado tablas temporales así que no se por donde me puede venir el fallo.

    <<

    El fallo viene de Visual Studio, que no es capaz de generar el table adapter cuando los datos provienen de una tabla temporal. Sencillamente este escenario no está soportado por los diseñadores de table adapter.

    Por otra parte, en general, hay que evitar el uso de tablas temporales, sólo deben usarse cuando se tenga una buena razón para ello, en tu caso, simplemente no tiene ningún sentido hacerlo, el procedimiento debería ejecutar la select y ya está, y quitar todo lo relativo a la tabla temporal.



    Jesús López


    EntityLite a lightweight, database first, micro orm

    viernes, 9 de enero de 2015 10:51
  • Ah,

    ¿De verdad vas a llamar al procedimiento  [TRANSACTSQL-1] ? No parece ser un nombre muy descriptivo que digamos.



    Jesús López


    EntityLite a lightweight, database first, micro orm

    viernes, 9 de enero de 2015 10:53
  • Hola Jesús según tengo entendido las tablas temporales en memoria ram tienen un procesamiento más rápido que las tablas alojadas en disco, por ello necesito utilizar este tipo de tabla ya que voy a trabajar con muchos registros y tb voy a hacer cálculos con ella e insertar nuevos campos cuando los necesite.

    Por ello te consulto de que otra forma puedo gestionar tablas temporales sin utilzar table adapter.

    Saluditos, Charo


    Saluditos, Charo

    viernes, 9 de enero de 2015 12:29
  • Ese procedimiento almacenado se ejecutará más rápido sin la tabla temporal que con la tabla temporal.

    Las tablas temporales se alojan en la base de datos tempdb, no en memoria. Por otra parte en ese procedimiento creas una tabla temporal, luego se leen las tablas base, el resultado lo guardas en la tabla temporal, y luego lees la tabla temporal. ¿Cómo puede ser eso más rápido que leer sólo las tablas base?

    Créeme, llevo muchos años trabajando con SQL Server. La primera tabla temporal la cree con SQL Server 6.5 allá por los años noventa y tantos y sé lo que estoy diciendo.

    No digo que no uses nunca tablas temporales. Hay ciertos casos extremos en los que pueden aumentar el rendimiento, pero en la inmensa mayoría de ello, lo que hacen es todo lo contrario.



    Jesús López


    EntityLite a lightweight, database first, micro orm


    • Editado Jesús López viernes, 9 de enero de 2015 12:49 x
    • Marcado como respuesta charoeci1 viernes, 9 de enero de 2015 17:55
    viernes, 9 de enero de 2015 12:40
  • >>

    Por ello te consulto de que otra forma puedo gestionar tablas temporales sin utilzar table adapter.

    <<

    Puedes usar un SqlDataAdapter en vez de los table adapter. O puedes ejecutar el procedimiento con SqlCommand.ExecuteReader y cargar una lista de entidades a partir del DataReader devuelto. O puedes usar EntityLite para ejecutar el procedimiento y obtener una lista de entidades. O puedes usar Entity Framework o NHibernate, etc, etc.



    Jesús López


    EntityLite a lightweight, database first, micro orm

    • Marcado como respuesta charoeci1 viernes, 9 de enero de 2015 17:57
    viernes, 9 de enero de 2015 12:53
  • Apoyo lo que dice Jesús el abuso de tablas temporales puede hacer que un query vaya mas rapido en especial si creas mucho, primero que nada si la tempdb no esta correctamente hecha (o con tamaños iniciales) puedes disparar muchos crecimientos, luego de eso esto debera de crear estadisticas para cada 1 de esto y sin indices las busquedas seran table scans que seran mucho más lentos.
    viernes, 9 de enero de 2015 14:18
  • Charo,

    Bajo el escenario que planteas todos tendremos la misma opinión. ¿Para qué usas esa tabla temporal?. No tiene ningún sentido dentro del procedimiento que nos muestras. Devuelve el select sin hacer la inserción previa a la tabla temporal.

    Ahora, - suele suceder -  que nos estés "ocultando" el verdadero escenario y sólo este fue un ejemplo de como utilizar tablas temporales. Dependiendo de lo que quieras hacer hay soluciones más rápidas como que en vez de tablas temporales es mejor utilizar variables de tipo table o ver la opción de crear vistas (materializadas o no), etc. Como vez la solución depende del problema.

    Si este es el escenario que tienes, quita la tabla temporal, a menos que tengas un sustento claro para su uso que no hayamos podido ver sería bueno que nos lo comentes.

    Si la solución propuesta atendió su consulta no olvide marcarla como respuesta.


    Willams Morales P.
    Arequipa - Perú

    viernes, 9 de enero de 2015 14:42
  • Te recomiendo mucho esta lectura personalmente en la mayoria de mis casos uso CTE cuando necesito mantener pequeños data set pero sinceramente no veo el uso como bien dices la tabla se queda en memoria debido a que se sobre entiende que sera un uso limitado pero no estas considerando todo le tiempo de creacion y acciones variadas.

    http://www.sqlservercentral.com/Forums/Topic415829-338-1.aspx


    • Editado Enrique AA viernes, 9 de enero de 2015 14:53
    viernes, 9 de enero de 2015 14:49
  • Ok, entendido Jesús. Tomo buena nota de tus consejos. Voy a replantearme entonces esto de usar tablas temporales pues es obvio que no tienen porqué ser mas rapidas.

    Mil gracias por tu ayuda.


    Charo


    Saluditos, Charo

    viernes, 9 de enero de 2015 17:54
  • Como nota si pueden ser una ganancia de velocidad, mucho depende tambien de tu hardware software y como este diseñada la base, solamente haz pruebas y ve que es mejor para tu caso, no todos los escenarios son iguales y no te podemos garantizar algo sin conocer tu ambiente y lo que consultas.
    viernes, 9 de enero de 2015 18:18
  • Hola Willams.

    Mi pregunta se basaba en un ejemplo real en el que estoy trabajando ahora mismo.

    No obstante, mi interés por las tablas temporales viene derivado sobre todo de ver como puedo procesar de la forma más rápida posible lo siguiente:

    En sucesivos pasos del programa que estoy desarrollando necesitaré procesar miles de filas que he de introducir en una tabla. Además tendré que insertar nuevos campos en dicha tabla los cuales tendré que rellenar con datos como medias moviles de un campo determinado en las ultimas n filas, calculos sobre varias columnas, etc etc. En resumen que seran tablas que aparte de tener un tamaño considerable soportaran una carga de calculos e inserciones incluso mas importante si cabe.

    Además estas tablas solo las necesito mientras esté abierta la sesión de trabajo en sql. Una vez cerrada estas tablas puedes desaparecer.

    Por ese motivo he deducido que quizás las tablas temporales eran la mejor opcion sobre todo por el tema de la velocidad de procesamiento de sus datos. En este sentido quizás ahora teneis mejor información de mi consulta sobre este tipo de tablas en sql.

    Gracias

    Charo


    Saluditos, Charo

    viernes, 9 de enero de 2015 22:51
  • Tengo curiosidad Charo estas haciendo una carga masiva de datos para una DWH? si es asi porque no usas un area de staging?
    viernes, 9 de enero de 2015 23:38
  • Hola Enrique.

    Perdoname pero mi nivel de sql no me permite saber a que te refieres. Qué es DWH? Y un area de Stagiing?  Acabo de buscarlo en la red y parece ser que tiene que ver con asuntos de mineria de datos.

    Lo que estoy desarrollando es un software para el control estadístico de la labor comercial y ventas de una empresa.


    Saluditos, Charo


    • Editado charoeci1 sábado, 10 de enero de 2015 0:15
    sábado, 10 de enero de 2015 0:05
  • No era otra cosa pero bueno DWH es Data ware house y basicamente es un historico de datos que normalmente son usados para inteligencia de negocios.

    Staging es algo como una area donde caen datos crudos (una base de datos) y estos son usados para ser modificados y crear la DWH como tal, como planteabas la situación me parecia que era esto, sino vas a consevar las tablas, no veo que te impida el hacer los calculos o movimientos que tengas planeados sobre la tabla misma.

    sábado, 10 de enero de 2015 0:14
  • Charo,

    Las soluciones comerciales hoy en día requieren información selecta, resumida y oportuna a cualquier nivel: gerencia, jefatura de ventas, representantes comerciales, etc y las soluciones de BI van encaminadas a ello. Seguramente poco a poco empezarás a saber de ellas.

    Te comento que tenemos un cliente al que hemos abordado una solución comercial con temas de gestión de objetivos de ventas, control de zonas, comportamiento del cliente, logro de cuotas, gestión de oportunidades, comportamiento del mercado, etc etc. Hoy en día se convirtio en una plataforma de BI, pero antes de ello quizá fue una solución como la que intentas realizar.

    Dependiendo del requerimiento o las necesidades o del tamaño de la información es que puedes presentar la disponibilidad de la misma al 100%, lo que te sugiero es que sea la bd quién te preparé todo lo requerido, apoyándote con vistas, funciones o procedimientos que te permitan reutilizar ciertas cálculos, etc.

    Lo que deberías de llegar a tener es una fuente de datos donde esté todo listo (algo de ello te comentaba Enrique al referirse a un DWH pero en menor escala seguramente en tu caso), finalmente lo que requieres es una almacén de datos donde todas tus variables a utilizar y avances estén a mano.

    Suerte!

    sábado, 10 de enero de 2015 0:23
  • Gracias a todos por vuestras respuestas y consejos

    Saluditos, Charo

    sábado, 10 de enero de 2015 11:26