SQL Server SELECT INTO @variable?

250

Tengo el siguiente código en uno de mis Sql (2008) Stored Procs que se ejecuta perfectamente:

    CREATE PROCEDURE [dbo].[Item_AddItem]
        @CustomerId uniqueidentifier,
        @Description nvarchar(100),
        @Type int,
        @Username nvarchar(100),
    AS
    BEGIN

        DECLARE @TopRelatedItemId uniqueidentifier;
        SET @TopRelatedItemId = 
        (
           SELECT top(1) RelatedItemId 
           FROM RelatedItems 
           WHERE CustomerId = @CustomerId
        ) 

        DECLARE @TempItem TABLE
        (
            ItemId uniqueidentifier,
            CustomerId uniqueidentifier,
            Description nvarchar(100),
            Type int,
            Username nvarchar(100),
            TimeStamp datetime
        );

        INSERT INTO Item
        OUTPUT INSERTED.* INTO @TempItem
        SELECT NEWID(), @CustomerId, @Description, @Type, @Username, GETDATE()

        SELECT
            ItemId,
            CustomerId,
            @TopRelatedItemId,
            Description,
            Type,
            Username,
            TimeStamp
        FROM
            @TempItem
END
GO

Entonces la pregunta para ustedes es si existe la posibilidad de hacer algo en la línea de:

DECLARE @TempCustomer TABLE
(
   CustomerId uniqueidentifier,
   FirstName nvarchar(100),
   LastName nvarchar(100),
   Email nvarchar(100)
);
SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email 
INTO 
    @TempCustomer 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId

¿Para poder reutilizar estos datos de la memoria en otras declaraciones siguientes? SQL Server se ajusta a la declaración anterior, sin embargo, no quiero tener que crear variables separadas e inicializar cada una de ellas a través de una declaración SELECT separada en la misma tabla ... ¡¡¡UGH !!!

¿Alguna sugerencia sobre cómo lograr algo similar sin múltiples consultas en la misma tabla?

Bleepzter
fuente
1
"para crear variables separadas e inicializar cada una de ellas a través de una instrucción SELECT separada" - ¿por qué necesitarías hacer eso? declare @t tableuna vez, y si necesita reutilizarlo, dispare un DELETE @TempCustomerantes de insertarlo nuevamente
RichardTheKiwi

Respuestas:

204

No puede SELECCIONAR ... EN ... una TABLA VARIABLE. Lo mejor que puede hacer es crearlo primero, luego insertarlo. Tu segundo fragmento tiene que ser

DECLARE @TempCustomer TABLE
(
   CustomerId uniqueidentifier,
   FirstName nvarchar(100),
   LastName nvarchar(100),
   Email nvarchar(100)
);
INSERT INTO 
    @TempCustomer 
SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId
RichardTheKiwi
fuente
55
Debe tener en cuenta que esto también funciona bien en un contexto CTE. Bazinga!
Michael Krauklis
44
¿Alguien tiene una respuesta de por qué uno no puede seleccionar en una variable de tabla como puede hacerlo con una tabla temporal real?
KSwift87
504

Si desea simplemente asignar algunas variables para su uso posterior, puede hacerlas de una sola vez con algo en esta línea:

declare @var1 int,@var2 int,@var3 int;

select 
    @var1 = field1,
    @var2 = field2,
    @var3 = field3
from
    table
where
    condition

Si ese es el tipo de cosas que buscas

dougajmcdonald
fuente
1
La mejor respuesta es, pero ¿qué pasa si los resultados son más de uno?
capitano666
Si los resultados son más de uno, obtendrá uno de los valores disponibles. ¡Eso podría ser un rompecabezas interesante! Ver mssqltips.com/sqlservertip/1888/…
Smandoli
8
Para forzar que la consulta devuelva una sola fila, use SELECT TOP 1
Adrian el
1
@Adrian Sí, la consulta anterior supone que ha seleccionado una sola fila. También puede usar las funciones de ordenamiento y agregado si desea una lógica más sofisticada.
dougajmcdonald
1
En caso de que no esté utilizando el tipo de base de datos que está utilizando el OP, no todos admiten TOP 1 como mencionó Adrian. SQL Server / MS Access usa TOP, MySQL usa LIMIT y Oracle usa ROWNUM. Consulte w3schools.com/sql/sql_top.asp para obtener más información.
Tyler
33

Puedes hacerlo:

SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email
INTO #tempCustomer 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId

Entonces despúes

SELECT CustomerId FROM #tempCustomer

no necesita declarar la estructura de #tempCustomer

Victor Ribeiro da Silva Eloy
fuente
3
@webturner Ninguno de esos puntos es cierto. Las tablas temporales no tienen un alcance fuera del proceso y las variables de tabla no son más "memoria solamente" que las tablas temporales.
Martin Smith
77
No se olvide de añadir un DROP TABLE #tempCustomercuando #tempCustomerya no se necesita otra manera la próxima seleccione provocará un #tempCustomer already existserror
ViRuSTriNiTy
15

Parece que su sintaxis está ligeramente fuera. Esto tiene algunos buenos ejemplos.

DECLARE @TempCustomer TABLE
(
   CustomerId uniqueidentifier,
   FirstName nvarchar(100),
   LastName nvarchar(100),
   Email nvarchar(100)
);
INSERT @TempCustomer 
SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId

Entonces despúes

SELECT CustomerId FROM @TempCustomer
Pat L
fuente
2

Parece que quieres tablas temporales. http://www.sqlteam.com/article/temporary-tables

Tenga en cuenta que #TempTable está disponible en todo su SP.

Tenga en cuenta que ## TempTable está disponible para todos.

Valamas
fuente
2
## temptable - hasta que el propietario (creador) lo elimine o se desconecte
RichardTheKiwi
44
No quiero tablas temporales. Las tablas temporales son caras y lentas. Solo quiero mantener un poco de datos para un registro específico durante un pequeño período de tiempo y ponerlos a disposición de múltiples declaraciones SQL, sin búsquedas posteriores. Dado que las variables de tabla tienen un alcance dentro del procedimiento almacenado se definieron en, ellos son la solución perfecta para almacenar datos tuppled para que una llamada almacenado proc ...
bleepzter
3
También se me olvidó mencionar que la base de datos reside en Azure ... No quiero introducir un lío en la administración de tablas temporales.
bleepzter
La tabla variable es el camino a seguir. declare @varTable Table (....)
ARLibertarian
1

Encontré su pregunta buscando una solución al mismo problema; y lo que otras respuestas no señalan es una forma de usar una variable para cambiar el nombre de la tabla para cada ejecución de su procedimiento en forma permanente, no temporal.

Hasta ahora, lo que hago es concatenar todo el código SQL con las variables a utilizar. Me gusta esto:

declare @table_name as varchar(30)
select @table_name = CONVERT(varchar(30), getdate(), 112)
set @table_name = 'DAILY_SNAPSHOT_' + @table_name

EXEC('
        SELECT var1, var2, var3
        INTO '+@table_name+'
        FROM my_view
        WHERE string = ''Strings must use double apostrophe''
    ');

Espero que ayude, pero podría ser engorroso si el código es demasiado grande, así que si has encontrado una mejor manera, ¡comparte!

Rodrigo
fuente
-2
"SELECT *
  INTO 
    @TempCustomer 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId"

Lo que significa crear una nueva @tempCustomervariable de tabla e insertar datos del cliente. Ya lo había declarado anteriormente, así que no es necesario volver a declararlo. Mejor ir con

INSERT INTO @tempCustomer SELECT * FROM Customer
koushik veldanda
fuente
44
No funciona Aún debe declarar la variable de tabla de antemano.
Johan Boulé