2011-01-28 17 views
183

tengo el siguiente código en una de My SQL (2008) procedimientos almacenados que ejecuta perfectamente bien:SQL Server ¿SELECCIONAR EN @variable?

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 

Así que la pregunta para ustedes es ¿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 que pueda volver a utilizar esta información de la memoria en otras declaraciones siguientes? SQL Server arroja un ajuste con 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 contra la misma tabla ... UGH !!!

¿Alguna sugerencia sobre cómo lograr algo a lo largo de las líneas sin múltiples consultas en la misma tabla?

+1

"para crear variables separadas e inicializar cada una de ellas mediante una instrucción SELECT separada" - ¿por qué tendrías que hacer eso? 'declare @t table' una vez, y si necesita reutilizarlo, active' DELETE @ TempCustomer' antes de insertarlo de nuevo – RichardTheKiwi

Respuesta

165

No se puede SELECCIONAR .. EN .. una TABLA VARIABLE. Lo mejor que puedes hacer es crearlo primero, luego insertarlo. Su 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 
+4

Debe tenerse en cuenta que esto también funciona bien en un contexto CTE. Bazinga! –

+2

¿Alguien tiene una respuesta sobre * por qué * uno no puede seleccionar en una variable de tabla como puede hacerlo con una tabla temporal real? – KSwift87

13

Parece que su sintaxis está ligeramente fuera. Esto tiene cierta good examples

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 

Luego, más tarde

SELECT CustomerId FROM @TempCustomer 
2

suena como usted quiere 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.

+2

## temptable - hasta que el propietario (creador) lo elimine o se desconecte – RichardTheKiwi

+3

No quiero tablas temporales. Las tablas de temperatura son caras y lentas. Solo quiero mantener un poco de datos para un registro específico por un período de tiempo pequeño y ponerlos a disposición de múltiples declaraciones SQL, sin búsquedas posteriores. Como las variables de tabla tienen alcance dentro del proceso almacenado en el que se definieron, son la solución perfecta para almacenar datos acumulados para esa llamada de proceso almacenada ... – bleepzter

+3

También olvidé mencionar que la base de datos reside en Azure ... No quiero introducir un lío en la administración de tablas temporales. – bleepzter

21

usted puede hacer esto:

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

luego

SELECT CustomerId FROM #tempCustomer 

que no es necesario declarar la estructura de #tempCustomer

+3

@webturner Ninguno de esos puntos es cierto. Las tablas temporales no tienen un ámbito fuera del proceso y las variables de la tabla ya no son "solo memoria" que las tablas temporales. –

+0

@MartinSmith Me corrigen, comentario eliminado. –

+3

No olvides agregar un 'DROP TABLE # tempCustomer' cuando' # tempCustomer' ya no sea necesario; de lo contrario, la siguiente selección provocará un error '#tempCustomer already exists' – ViRuSTriNiTy

384

Si quieres asignar simplemente para algunas variables uso posterior, puede hacerlas de una vez con algo parecido a estas líneas:

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

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

Si ese es el tipo de cosa que está buscando

+1

La mejor respuesta, ¿qué sucede si los resultados son más? ¿de una? – capitano666

+0

Si los resultados son más de uno, obtendrá uno de los valores disponibles. ¡Eso podría ser un rompecabezas interesante! Consulte https://www.mssqltips.com/sqlservertip/1888/when-to-use-set-vs-select-when-assigning-values-to-variables-in-sql-server – Smandoli

+5

Para forzar la consulta a devolver un uso de una sola fila SELECCIONAR SUPERIOR 1 – Adrian

-1
"SELECT * 
    INTO 
    @TempCustomer 
FROM 
    Customer 
WHERE 
    CustomerId = @CustomerId" 

lo que significa crear un nuevo @tempCustomer tablevariable y la inserción de los datos del Cliente. Ya lo has declarado arriba, así que no es necesario volver a declararlo. Mejor ir con

INSERT INTO @tempCustomer SELECT * FROM Customer 
+1

No funciona. Aún necesita declarar la variable de tabla de antemano. –

Cuestiones relacionadas