SQL Server SELECIONAR EM @ variável?

250

Eu tenho o seguinte código em um dos meus Sql (2008) Stored Procs que executa perfeitamente:

    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

Portanto, a pergunta para vocês é que existe a possibilidade de fazer algo como:

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 eu pudesse reutilizar esses dados da memória em outras declarações a seguir? O SQL Server se encaixa com a instrução acima, porém não quero criar variáveis ​​separadas e inicializar cada uma delas por meio de uma instrução SELECT separada na mesma tabela ... UGH !!!

Alguma sugestão sobre como conseguir algo nesse sentido sem várias consultas na mesma tabela?

bleepzter
fonte
1
"para criar variáveis ​​separadas e inicializar cada uma delas através de uma instrução SELECT separada" - por que você precisaria fazer isso? declare @t tableuma vez, e se você precisa de reutilizá-lo, disparar um DELETE @TempCustomerantes de inserir-lo novamente
RichardTheKiwi

Respostas:

204

Você não pode SELECIONAR .. EM .. uma TABELA VARIÁVEL. O melhor que você pode fazer é criá-lo primeiro e depois inseri-lo. Seu segundo snippet precisa 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
fonte
5
Deve-se notar que isso também funciona bem em um contexto CTE. Bazinga!
Michael Krauklis
4
Alguém tem uma resposta sobre por que não se pode selecionar em uma variável de tabela como você pode com uma tabela temporária real?
KSwift87
504

Se você quiser simplesmente atribuir algumas variáveis ​​para uso posterior, você pode fazê-las de uma só vez com algo ao longo destas linhas:

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

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

Se esse é o tipo de coisa que você procura

dougajmcdonald
fonte
1
Melhor resposta imho, mas o que acontece se os resultados forem mais de um?
Capitano666
Se os resultados forem mais de um, você obterá um dos valores disponíveis. Isso poderia criar um quebra-cabeça interessante! Veja mssqltips.com/sqlservertip/1888/…
Smandoli
8
Para forçar a consulta para retornar uma única utilização linha SELECT TOP 1
Adrian
1
@Adrian Sim, a consulta acima pressupõe que você selecionou uma única linha. Você também pode usar funções de ordenação e agregação se desejar uma lógica mais sofisticada.
precisa saber é o seguinte
1
Caso você não esteja usando o tipo de banco de dados que o OP está usando, nem todos suportam o TOP 1, como Adrian mencionou. O SQL Server / MS Access usa TOP, o MySQL usa LIMIT e o Oracle usa ROWNUM. Consulte w3schools.com/sql/sql_top.asp para obter mais informações.
Tyler
33

você consegue fazer isso:

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

depois

SELECT CustomerId FROM #tempCustomer

você não precisa declarar a estrutura de #tempCustomer

Victor Ribeiro da Silva Eloy
fonte
3
@webturner Nenhum desses pontos é verdadeiro. As tabelas temporárias não têm escopo definido fora do proc e as variáveis ​​da tabela não têm mais "apenas memória" do que as tabelas temporárias.
Martin Smith
7
Não se esqueça de adicionar um DROP TABLE #tempCustomerquando #tempCustomernão for mais necessário, caso contrário, a próxima seleção causará um #tempCustomer already existserro.
ViRuSTriNiTy
15

Parece que sua sintaxe está um pouco fora. Isso tem alguns bons exemplos

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

Depois

SELECT CustomerId FROM @TempCustomer
Pat L
fonte
2

Parece que você quer tabelas temporárias. http://www.sqlteam.com/article/temporary-tables

Observe que #TempTable está disponível em todo o seu SP.

Observe que o ## TempTable está disponível para todos.

Valamas
fonte
2
## tentable - até que o proprietário (criador) o exclua ou seja desconectado #
RichardTheKiwi
4
Eu não quero tabelas temporárias. As tabelas temporárias são caras e lentas. Eu só quero manter um pouco de dados para um registro específico por um pequeno período de tempo e disponibilizá-lo para várias instruções sql, sem pesquisas subsequentes. Desde variáveis de tabela têm escopo dentro do proc armazenados foram definidos, eles são a solução perfeita para armazenar dados tuppled para aquele armazenado chamada proc ...
bleepzter
3
Também esqueci de mencionar que o banco de dados reside no Azure .... Não quero introduzir uma bagunça no gerenciamento de tabelas temporárias.
bleepzter
Tabela variável é o caminho a percorrer. declarar @varTable Tabela (....)
ARLibertarian
1

Encontrei sua pergunta procurando uma solução para o mesmo problema; e que outras respostas falham em apontar é uma maneira de usar uma variável para alterar o nome da tabela para cada execução de seu procedimento de forma permanente, não temporária.

Até agora, o que faço é concatenar todo o código SQL com as variáveis ​​a serem usadas. Como isso:

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 ajude, mas pode ser complicado se o código for muito grande, por isso, se você encontrou uma maneira melhor, compartilhe!

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

O que significa criar uma nova @tempCustomervariável de tabela e inserir dados do cliente. Você já o havia declarado acima, portanto não há necessidade de declarar novamente. Melhor ir com

INSERT INTO @tempCustomer SELECT * FROM Customer
koushik veldanda
fonte
4
Isso não funciona. Você ainda precisa declarar a variável da tabela antecipadamente.
Johan Boulé